<!DOCTYPE html>
<html lang="en">
    <head hexo-theme='https://github.com/volantis-x/hexo-theme-volantis/#5.8.0'>
  <meta name="generator" content="Hexo 6.3.0">
  <meta name="Volantis" content="5.8.0">
  <meta charset="utf-8">
  <!-- SEO相关 -->
  
  <link rel="canonical" href="http://8.219.11.28/2024/02/23/单体-jsp/"/>
  <!-- 渲染优化 -->
    <meta http-equiv='x-dns-prefetch-control' content='on' />
      <link rel='dns-prefetch' href='https://unpkg.com'>
      <link rel="preconnect" href="https://unpkg.com" crossorigin>
  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta http-equiv="Content-Security-Policy" content=" default-src 'self' https:; block-all-mixed-content; base-uri 'self' https:; form-action 'self' https:; worker-src 'self' https:; connect-src 'self' https: *; img-src 'self' data: https: *; media-src 'self' https: *; font-src 'self' data: https: *; frame-src 'self' https: *; manifest-src 'self' https: *; child-src https:; script-src 'self' https: 'unsafe-inline' *; style-src 'self' https: 'unsafe-inline' *; ">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
  <meta content="black-translucent" name="apple-mobile-web-app-status-bar-style">
  <meta content="telephone=no" name="format-detection">
  <!-- import head_begin begin -->
  <!-- import head_begin end -->
  <!-- Custom Files headBegin begin-->
  
  <!-- Custom Files headBegin end-->
  <!-- front-matter head_begin begin -->
  <!-- front-matter head_begin end -->
  <link rel="preload" href="/css/style.css" as="style">
  <link rel="preload" href="https://unpkg.com/volantis-static@0.0.1654736714924/media/fonts/VarelaRound/VarelaRound-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous">
<link rel="preload" href="https://unpkg.com/volantis-static@0.0.1654736714924/media/fonts/UbuntuMono/UbuntuMono-Regular.ttf" as="font" type="font/ttf" crossorigin="anonymous">

  <!-- feed -->
  <!-- 页面元数据 -->
  <title>欢迎来到我的个人博客~</title>
  <meta name="keywords" content="null">
  <meta desc name="description" content="这些技术大部分是自己总结的，非官方 - 天明 - 欢迎来到我的个人博客~">
  
<meta property="og:type" content="article">
<meta property="og:title" content="欢迎来到我的个人博客~">
<meta property="og:url" content="http://8.219.11.28/2024/02/23/%E5%8D%95%E4%BD%93-JSP/index.html">
<meta property="og:site_name" content="欢迎来到我的个人博客~">
<meta property="og:description" content="一、JSP概述1.1 Servlet使用的不足 Servlet是一个动态网页技术，客户端通过请求Servlet类可以相应给客户端一个动态网页，但是Servlet在使用过程中有什么不足之处呢？  开发方式麻烦：继承HttpServlet父类、重写doGet&#x2F;doPost、Servlet配置  项目更新麻烦：Servlet类中的代码发生改变，需要重新编译、部署、启动Tomcat  网页呈现复">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png">
<meta property="article:published_time" content="2024-02-23T14:27:45.421Z">
<meta property="article:modified_time" content="2024-01-07T15:46:22.673Z">
<meta property="article:author" content="天明">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png">
  <style>
    /* 首屏样式 */
    #safearea {
  display: none;
}
:root {
  --color-site-body: #f4f4f4;
  --color-site-bg: #f4f4f4;
  --color-site-inner: #fff;
  --color-site-footer: #666;
  --color-card: #fff;
  --color-text: #444;
  --color-block: #f6f6f6;
  --color-inlinecode: #c74f00;
  --color-codeblock: #fff7ea;
  --color-h1: #3a3a3a;
  --color-h2: #3a3a3a;
  --color-h3: #333;
  --color-h4: #444;
  --color-h5: #555;
  --color-h6: #666;
  --color-p: #444;
  --color-list: #666;
  --color-list-hl: #30ad91;
  --color-meta: #888;
  --color-read-bkg: #e0d8c8;
  --color-read-post: #f8f1e2;
  --color-copyright-bkg: #f5f5f5;
}
* {
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  outline: none;
  margin: 0;
  padding: 0;
}
*::-webkit-scrollbar {
  height: 4px;
  width: 4px;
}
*::-webkit-scrollbar-track-piece {
  background: transparent;
}
*::-webkit-scrollbar-thumb {
  background: #3dd9b6;
  cursor: pointer;
  border-radius: 2px;
  -webkit-border-radius: 2px;
}
*::-webkit-scrollbar-thumb:hover {
  background: #ff5722;
}
html {
  color: var(--color-text);
  width: 100%;
  height: 100%;
  font-family: UbuntuMono, "Varela Round", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, Menlo, Monaco, monospace, sans-serif;
  font-size: 16px;
}
html >::-webkit-scrollbar {
  height: 4px;
  width: 4px;
}
html >::-webkit-scrollbar-track-piece {
  background: transparent;
}
html >::-webkit-scrollbar-thumb {
  background: #54b5a0 linear-gradient(45deg, rgba(255,255,255,0.4) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.4) 50%, rgba(255,255,255,0.4) 75%, transparent 75%, transparent);
  cursor: pointer;
  border-radius: 2px;
  -webkit-border-radius: 2px;
}
html >::-webkit-scrollbar-thumb:hover {
  background: #54b5a0 linear-gradient(45deg, rgba(255,255,255,0.4) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.4) 50%, rgba(255,255,255,0.4) 75%, transparent 75%, transparent);
}
body {
  background-color: var(--color-site-body);
  text-rendering: optimizelegibility;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
}
body.modal-active {
  overflow: hidden;
}
@media screen and (max-width: 680px) {
  body.modal-active {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
  }
}
a {
  color: #2092ec;
  cursor: pointer;
  text-decoration: none;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
a:hover {
  color: #ff5722;
}
a:active,
a:hover {
  outline: 0;
}
ul,
ol {
  padding-left: 0;
}
ul li,
ol li {
  list-style: none;
}
header {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
}
img {
  border: 0;
  background: none;
  max-width: 100%;
}
svg:not(:root) {
  overflow: hidden;
}
hr {
  -moz-box-sizing: content-box;
  box-sizing: content-box;
  -webkit-box-sizing: content-box;
  -moz-box-sizing: content-box;
  height: 0;
  border: 0;
  border-radius: 1px;
  -webkit-border-radius: 1px;
  border-bottom: 1px solid rgba(68,68,68,0.1);
}
button,
input {
  color: inherit;
  font: inherit;
  margin: 0;
}
button {
  overflow: visible;
  text-transform: none;
  -webkit-appearance: button;
  cursor: pointer;
}
@supports (backdrop-filter: blur(20px)) {
  .blur {
    background: rgba(255,255,255,0.9) !important;
    backdrop-filter: saturate(200%) blur(20px);
  }
}
.shadow {
  box-shadow: 0 1px 2px 0px rgba(0,0,0,0.1);
  -webkit-box-shadow: 0 1px 2px 0px rgba(0,0,0,0.1);
}
.shadow.floatable {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
.shadow.floatable:hover {
  box-shadow: 0 2px 4px 0px rgba(0,0,0,0.1), 0 4px 8px 0px rgba(0,0,0,0.1), 0 8px 16px 0px rgba(0,0,0,0.1);
  -webkit-box-shadow: 0 2px 4px 0px rgba(0,0,0,0.1), 0 4px 8px 0px rgba(0,0,0,0.1), 0 8px 16px 0px rgba(0,0,0,0.1);
}
#l_cover {
  min-height: 64px;
}
.cover-wrapper {
  top: 0;
  left: 0;
  max-width: 100%;
  height: 100vh;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  flex-wrap: nowrap;
  -webkit-flex-wrap: nowrap;
  -khtml-flex-wrap: nowrap;
  -moz-flex-wrap: nowrap;
  -o-flex-wrap: nowrap;
  -ms-flex-wrap: nowrap;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: vertical;
  -moz-box-orient: vertical;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  align-items: center;
  align-self: center;
  align-content: center;
  color: var(--color-site-inner);
  padding: 0 16px;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  position: relative;
  overflow: hidden;
  margin-bottom: -100px;
}
.cover-wrapper .cover-bg {
  position: absolute;
  width: 100%;
  height: 100%;
  background-position: center;
  background-size: cover;
  -webkit-background-size: cover;
  -moz-background-size: cover;
}
.cover-wrapper .cover-bg.lazyload:not(.loaded) {
  opacity: 0;
  -webkit-opacity: 0;
  -moz-opacity: 0;
}
.cover-wrapper .cover-bg.lazyload.loaded {
  animation-delay: 0s;
  animation-duration: 0.5s;
  animation-fill-mode: forwards;
  animation-timing-function: ease-out;
  animation-name: fadeIn;
}
@-moz-keyframes fadeIn {
  0% {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
    filter: blur(12px);
    transform: scale(1.02);
    -webkit-transform: scale(1.02);
    -khtml-transform: scale(1.02);
    -moz-transform: scale(1.02);
    -o-transform: scale(1.02);
    -ms-transform: scale(1.02);
  }
  100% {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@-webkit-keyframes fadeIn {
  0% {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
    filter: blur(12px);
    transform: scale(1.02);
    -webkit-transform: scale(1.02);
    -khtml-transform: scale(1.02);
    -moz-transform: scale(1.02);
    -o-transform: scale(1.02);
    -ms-transform: scale(1.02);
  }
  100% {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@-o-keyframes fadeIn {
  0% {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
    filter: blur(12px);
    transform: scale(1.02);
    -webkit-transform: scale(1.02);
    -khtml-transform: scale(1.02);
    -moz-transform: scale(1.02);
    -o-transform: scale(1.02);
    -ms-transform: scale(1.02);
  }
  100% {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@keyframes fadeIn {
  0% {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
    filter: blur(12px);
    transform: scale(1.02);
    -webkit-transform: scale(1.02);
    -khtml-transform: scale(1.02);
    -moz-transform: scale(1.02);
    -o-transform: scale(1.02);
    -ms-transform: scale(1.02);
  }
  100% {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
.cover-wrapper .cover-body {
  z-index: 1;
  position: relative;
  width: 100%;
  height: 100%;
}
.cover-wrapper#full {
  height: calc(100vh + 100px);
  padding-bottom: 100px;
}
.cover-wrapper#half {
  max-height: 640px;
  min-height: 400px;
  height: calc(36vh - 64px + 200px);
}
.cover-wrapper #scroll-down {
  width: 100%;
  height: 64px;
  position: absolute;
  bottom: 100px;
  text-align: center;
  cursor: pointer;
}
.cover-wrapper #scroll-down .scroll-down-effects {
  color: #fff;
  font-size: 24px;
  line-height: 64px;
  position: absolute;
  width: 24px;
  left: calc(50% - 12px);
  text-shadow: 0 1px 2px rgba(0,0,0,0.1);
  animation: scroll-down-effect 1.5s infinite;
  -webkit-animation: scroll-down-effect 1.5s infinite;
  -khtml-animation: scroll-down-effect 1.5s infinite;
  -moz-animation: scroll-down-effect 1.5s infinite;
  -o-animation: scroll-down-effect 1.5s infinite;
  -ms-animation: scroll-down-effect 1.5s infinite;
}
@-moz-keyframes scroll-down-effect {
  0% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
  50% {
    top: -16px;
    opacity: 0.4;
    -webkit-opacity: 0.4;
    -moz-opacity: 0.4;
  }
  100% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@-webkit-keyframes scroll-down-effect {
  0% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
  50% {
    top: -16px;
    opacity: 0.4;
    -webkit-opacity: 0.4;
    -moz-opacity: 0.4;
  }
  100% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@-o-keyframes scroll-down-effect {
  0% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
  50% {
    top: -16px;
    opacity: 0.4;
    -webkit-opacity: 0.4;
    -moz-opacity: 0.4;
  }
  100% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@keyframes scroll-down-effect {
  0% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
  50% {
    top: -16px;
    opacity: 0.4;
    -webkit-opacity: 0.4;
    -moz-opacity: 0.4;
  }
  100% {
    top: 0;
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
.cover-wrapper .cover-body {
  margin-top: 64px;
  margin-bottom: 100px;
}
.cover-wrapper .cover-body,
.cover-wrapper .cover-body .top,
.cover-wrapper .cover-body .bottom {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: vertical;
  -moz-box-orient: vertical;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  -webkit-justify-content: center;
  -khtml-justify-content: center;
  -moz-justify-content: center;
  -o-justify-content: center;
  -ms-justify-content: center;
  max-width: 100%;
}
.cover-wrapper .cover-body .bottom {
  margin-top: 32px;
}
.cover-wrapper .cover-body .title {
  font-family: "Varela Round", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, Helvetica, monospace;
  font-size: 3.125rem;
  line-height: 1.2;
  text-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.cover-wrapper .cover-body .subtitle {
  font-size: 20px;
}
.cover-wrapper .cover-body .logo {
  max-height: 120px;
  max-width: calc(100% - 4 * 16px);
}
@media screen and (min-height: 1024px) {
  .cover-wrapper .cover-body .title {
    font-size: 3rem;
  }
  .cover-wrapper .cover-body .subtitle {
    font-size: 1.05rem;
  }
  .cover-wrapper .cover-body .logo {
    max-height: 150px;
  }
}
.cover-wrapper .cover-body .m_search {
  position: relative;
  max-width: calc(100% - 16px);
  width: 320px;
  vertical-align: middle;
}
.cover-wrapper .cover-body .m_search .form {
  position: relative;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  width: 100%;
}
.cover-wrapper .cover-body .m_search .icon,
.cover-wrapper .cover-body .m_search .input {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
.cover-wrapper .cover-body .m_search .icon {
  position: absolute;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  line-height: 2.5rem;
  width: 32px;
  top: 0;
  left: 5px;
  color: rgba(68,68,68,0.75);
}
.cover-wrapper .cover-body .m_search .input {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  height: 2.5rem;
  width: 100%;
  box-shadow: none;
  -webkit-box-shadow: none;
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  font-size: 0.875rem;
  -webkit-appearance: none;
  padding-left: 36px;
  border-radius: 1.4rem;
  -webkit-border-radius: 1.4rem;
  background: rgba(255,255,255,0.6);
  backdrop-filter: blur(10px);
  border: none;
  color: var(--color-text);
}
@media screen and (max-width: 500px) {
  .cover-wrapper .cover-body .m_search .input {
    padding-left: 36px;
  }
}
.cover-wrapper .cover-body .m_search .input:hover {
  background: rgba(255,255,255,0.8);
}
.cover-wrapper .cover-body .m_search .input:focus {
  background: #fff;
}
.cover-wrapper .list-h {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: horizontal;
  -moz-box-orient: horizontal;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
  flex-wrap: wrap;
  -webkit-flex-wrap: wrap;
  -khtml-flex-wrap: wrap;
  -moz-flex-wrap: wrap;
  -o-flex-wrap: wrap;
  -ms-flex-wrap: wrap;
  align-items: stretch;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.cover-wrapper .list-h a {
  -webkit-box-flex: 1;
  -moz-box-flex: 1;
  -webkit-flex: 1 0;
  -ms-flex: 1 0;
  flex: 1 0;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  font-weight: 600;
}
.cover-wrapper .list-h a img {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  border-radius: 2px;
  -webkit-border-radius: 2px;
  margin: 4px;
  min-width: 40px;
  max-width: 44px;
}
@media screen and (max-width: 768px) {
  .cover-wrapper .list-h a img {
    min-width: 36px;
    max-width: 40px;
  }
}
@media screen and (max-width: 500px) {
  .cover-wrapper .list-h a img {
    margin: 2px 4px;
    min-width: 32px;
    max-width: 36px;
  }
}
@media screen and (max-width: 375px) {
  .cover-wrapper .list-h a img {
    min-width: 28px;
    max-width: 32px;
  }
}
.cover-wrapper {
  max-width: 100%;
}
.cover-wrapper.search .bottom .menu {
  margin-top: 16px;
}
.cover-wrapper.search .bottom .menu .list-h a {
  white-space: nowrap;
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: horizontal;
  -moz-box-orient: horizontal;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row;
  align-items: baseline;
  padding: 2px;
  margin: 4px;
  color: var(--color-site-inner);
  opacity: 0.75;
  -webkit-opacity: 0.75;
  -moz-opacity: 0.75;
  text-shadow: 0 1px 2px rgba(0,0,0,0.05);
  border-bottom: 2px solid transparent;
}
.cover-wrapper.search .bottom .menu .list-h a i {
  margin-right: 4px;
}
.cover-wrapper.search .bottom .menu .list-h a p {
  font-size: 0.9375rem;
}
.cover-wrapper.search .bottom .menu .list-h a:hover,
.cover-wrapper.search .bottom .menu .list-h a.active,
.cover-wrapper.search .bottom .menu .list-h a:active {
  opacity: 1;
  -webkit-opacity: 1;
  -moz-opacity: 1;
  border-bottom: 2px solid var(--color-site-inner);
}
.cover-wrapper.dock .menu,
.cover-wrapper.featured .menu,
.cover-wrapper.focus .menu {
  border-radius: 6px;
  -webkit-border-radius: 6px;
}
.cover-wrapper.dock .menu .list-h a,
.cover-wrapper.featured .menu .list-h a,
.cover-wrapper.focus .menu .list-h a {
  -webkit-box-direction: normal;
  -moz-box-direction: normal;
  -webkit-box-orient: vertical;
  -moz-box-orient: vertical;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  align-items: center;
  padding: 12px;
  line-height: 24px;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  border-bottom: none;
  text-align: center;
  align-content: flex-end;
  color: rgba(68,68,68,0.7);
  font-size: 1.5rem;
}
@media screen and (max-width: 500px) {
  .cover-wrapper.dock .menu .list-h a,
  .cover-wrapper.featured .menu .list-h a,
  .cover-wrapper.focus .menu .list-h a {
    padding: 12px 8px;
  }
}
.cover-wrapper.dock .menu .list-h a i,
.cover-wrapper.featured .menu .list-h a i,
.cover-wrapper.focus .menu .list-h a i {
  margin: 8px;
}
.cover-wrapper.dock .menu .list-h a p,
.cover-wrapper.featured .menu .list-h a p,
.cover-wrapper.focus .menu .list-h a p {
  font-size: 0.875rem;
}
.cover-wrapper.dock .menu .list-h a.active,
.cover-wrapper.featured .menu .list-h a.active,
.cover-wrapper.focus .menu .list-h a.active {
  background: var(--color-card);
  backdrop-filter: none;
}
.cover-wrapper.dock .menu .list-h a.active i,
.cover-wrapper.featured .menu .list-h a.active i,
.cover-wrapper.focus .menu .list-h a.active i,
.cover-wrapper.dock .menu .list-h a.active i+p,
.cover-wrapper.featured .menu .list-h a.active i+p,
.cover-wrapper.focus .menu .list-h a.active i+p {
  color: #3dd9b6;
}
.cover-wrapper.dock .menu .list-h a.active img+p,
.cover-wrapper.featured .menu .list-h a.active img+p,
.cover-wrapper.focus .menu .list-h a.active img+p {
  color: var(--color-text);
}
.cover-wrapper.dock .menu .list-h a:hover,
.cover-wrapper.featured .menu .list-h a:hover,
.cover-wrapper.focus .menu .list-h a:hover {
  background: var(--color-card);
}
.cover-wrapper.dock .top {
  margin-bottom: 48px;
}
.cover-wrapper.dock .menu {
  background: rgba(255,255,255,0.5);
  position: absolute;
  bottom: 0;
  max-width: 100%;
}
.cover-wrapper.dock .menu .list-h {
  flex-wrap: nowrap;
  -webkit-flex-wrap: nowrap;
  -khtml-flex-wrap: nowrap;
  -moz-flex-wrap: nowrap;
  -o-flex-wrap: nowrap;
  -ms-flex-wrap: nowrap;
  margin: 4px;
}
.cover-wrapper.dock .menu .list-h a+a {
  margin-left: 4px;
}
@media screen and (max-width: 500px) {
  .cover-wrapper.dock .menu .list-h {
    overflow-x: scroll;
  }
  .cover-wrapper.dock .menu .list-h::-webkit-scrollbar {
    height: 0;
    width: 0;
  }
  .cover-wrapper.dock .menu .list-h::-webkit-scrollbar-track-piece {
    background: transparent;
  }
  .cover-wrapper.dock .menu .list-h::-webkit-scrollbar-thumb {
    background: #3dd9b6;
    cursor: pointer;
    border-radius: 0;
    -webkit-border-radius: 0;
  }
  .cover-wrapper.dock .menu .list-h::-webkit-scrollbar-thumb:hover {
    background: #ff5722;
  }
}
@supports (backdrop-filter: blur(20px)) {
  .cover-wrapper.dock .menu {
    background: rgba(255,255,255,0.5);
    backdrop-filter: saturate(200%) blur(20px);
  }
}
@font-face {
  font-family: 'UbuntuMono';
  src: url("https://unpkg.com/volantis-static@0.0.1654736714924/media/fonts/UbuntuMono/UbuntuMono-Regular.ttf");
  font-weight: 'normal';
  font-style: 'normal';
  font-display: swap;
}
@font-face {
  font-family: 'Varela Round';
  src: url("https://unpkg.com/volantis-static@0.0.1654736714924/media/fonts/VarelaRound/VarelaRound-Regular.ttf");
  font-weight: 'normal';
  font-style: 'normal';
  font-display: swap;
}
.l_header {
  position: fixed;
  z-index: 1000;
  top: 0;
  width: 100%;
  height: 64px;
  background: var(--color-card);
  box-shadow: 0 1px 2px 0px rgba(0,0,0,0.1);
  -webkit-box-shadow: 0 1px 2px 0px rgba(0,0,0,0.1);
}
.l_header.auto {
  transition: opacity 0.4s ease;
  -webkit-transition: opacity 0.4s ease;
  -khtml-transition: opacity 0.4s ease;
  -moz-transition: opacity 0.4s ease;
  -o-transition: opacity 0.4s ease;
  -ms-transition: opacity 0.4s ease;
  visibility: hidden;
}
.l_header.auto.show {
  opacity: 1 !important;
  -webkit-opacity: 1 !important;
  -moz-opacity: 1 !important;
  visibility: visible;
}
.l_header .container {
  margin-left: 16px;
  margin-right: 16px;
}
.l_header #wrapper {
  height: 100%;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.l_header #wrapper .nav-main,
.l_header #wrapper .nav-sub {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  flex-wrap: nowrap;
  -webkit-flex-wrap: nowrap;
  -khtml-flex-wrap: nowrap;
  -moz-flex-wrap: nowrap;
  -o-flex-wrap: nowrap;
  -ms-flex-wrap: nowrap;
  justify-content: space-between;
  -webkit-justify-content: space-between;
  -khtml-justify-content: space-between;
  -moz-justify-content: space-between;
  -o-justify-content: space-between;
  -ms-justify-content: space-between;
  align-items: center;
}
.l_header #wrapper .nav-main {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
.l_header #wrapper.sub .nav-main {
  transform: translateY(-64px);
  -webkit-transform: translateY(-64px);
  -khtml-transform: translateY(-64px);
  -moz-transform: translateY(-64px);
  -o-transform: translateY(-64px);
  -ms-transform: translateY(-64px);
}
.l_header #wrapper .nav-sub {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
  opacity: 0;
  -webkit-opacity: 0;
  -moz-opacity: 0;
  height: 64px;
  width: calc(100% - 2 * 16px);
  position: absolute;
}
.l_header #wrapper .nav-sub ::-webkit-scrollbar {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
}
@media screen and (min-width: 2048px) {
  .l_header #wrapper .nav-sub {
    max-width: 55vw;
    margin: auto;
  }
}
.l_header #wrapper.sub .nav-sub {
  opacity: 1;
  -webkit-opacity: 1;
  -moz-opacity: 1;
}
.l_header #wrapper .title {
  position: relative;
  color: var(--color-text);
  padding-left: 24px;
  max-height: 64px;
}
.l_header #wrapper .nav-main .title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 0;
  line-height: 64px;
  padding: 0 24px;
  font-size: 1.25rem;
  font-family: "Varela Round", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, Helvetica, monospace;
}
.l_header #wrapper .nav-main .title img {
  height: 64px;
}
.l_header .nav-sub {
  max-width: 1080px;
  margin: auto;
}
.l_header .nav-sub .title {
  font-weight: bold;
  font-family: UbuntuMono, "Varela Round", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, Menlo, Monaco, monospace, sans-serif;
  line-height: 1.2;
  max-height: 64px;
  white-space: normal;
  flex-shrink: 1;
}
.l_header .switcher {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  line-height: 64px;
  align-items: center;
}
.l_header .switcher .s-toc {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
}
@media screen and (max-width: 768px) {
  .l_header .switcher .s-toc {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: -ms-flexbox /* TWEENER - IE 10 */;
    display: -webkit-flex /* NEW - Chrome */;
    display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
    display: flex;
  }
}
.l_header .switcher >li {
  height: 48px;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
  margin: 2px;
}
@media screen and (max-width: 500px) {
  .l_header .switcher >li {
    margin: 0 1px;
    height: 48px;
  }
}
.l_header .switcher >li >a {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  justify-content: center;
  -webkit-justify-content: center;
  -khtml-justify-content: center;
  -moz-justify-content: center;
  -o-justify-content: center;
  -ms-justify-content: center;
  align-items: center;
  width: 48px;
  height: 48px;
  padding: 0.85em 1.1em;
  border-radius: 100px;
  -webkit-border-radius: 100px;
  border: none;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
  color: #3dd9b6;
}
.l_header .switcher >li >a:hover {
  border: none;
}
.l_header .switcher >li >a.active,
.l_header .switcher >li >a:active {
  border: none;
  background: var(--color-site-bg);
}
@media screen and (max-width: 500px) {
  .l_header .switcher >li >a {
    width: 36px;
    height: 48px;
  }
}
.l_header .nav-sub .switcher {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
}
.l_header .m_search {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  height: 64px;
  width: 240px;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
@media screen and (max-width: 1024px) {
  .l_header .m_search {
    width: 44px;
    min-width: 44px;
  }
  .l_header .m_search input::placeholder {
    opacity: 0;
    -webkit-opacity: 0;
    -moz-opacity: 0;
  }
  .l_header .m_search:hover {
    width: 240px;
  }
  .l_header .m_search:hover input::placeholder {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@media screen and (min-width: 500px) {
  .l_header .m_search:hover .input {
    width: 100%;
  }
  .l_header .m_search:hover .input::placeholder {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
@media screen and (max-width: 500px) {
  .l_header .m_search {
    min-width: 0;
  }
  .l_header .m_search input::placeholder {
    opacity: 1;
    -webkit-opacity: 1;
    -moz-opacity: 1;
  }
}
.l_header .m_search .form {
  position: relative;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  width: 100%;
  align-items: center;
}
.l_header .m_search .icon {
  position: absolute;
  width: 36px;
  left: 5px;
  color: var(--color-meta);
}
@media screen and (max-width: 500px) {
  .l_header .m_search .icon {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: none;
  }
}
.l_header .m_search .input {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  padding-top: 8px;
  padding-bottom: 8px;
  line-height: 1.3;
  width: 100%;
  color: var(--color-text);
  background: #fafafa;
  box-shadow: none;
  -webkit-box-shadow: none;
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  padding-left: 40px;
  font-size: 0.875rem;
  border-radius: 8px;
  -webkit-border-radius: 8px;
  border: none;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
@media screen and (min-width: 500px) {
  .l_header .m_search .input:focus {
    box-shadow: 0 4px 8px 0px rgba(0,0,0,0.1);
    -webkit-box-shadow: 0 4px 8px 0px rgba(0,0,0,0.1);
  }
}
@media screen and (max-width: 500px) {
  .l_header .m_search .input {
    background: var(--color-block);
    padding-left: 8px;
    border: none;
  }
  .l_header .m_search .input:hover,
  .l_header .m_search .input:focus {
    border: none;
  }
}
@media (max-width: 500px) {
  .l_header .m_search {
    left: 0;
    width: 0;
    overflow: hidden;
    position: absolute;
    background: #fff;
    transition: all 0.28s ease;
    -webkit-transition: all 0.28s ease;
    -khtml-transition: all 0.28s ease;
    -moz-transition: all 0.28s ease;
    -o-transition: all 0.28s ease;
    -ms-transition: all 0.28s ease;
  }
  .l_header .m_search .input {
    border-radius: 32px;
    -webkit-border-radius: 32px;
    margin-left: 16px;
    padding-left: 16px;
  }
  .l_header.z_search-open .m_search {
    width: 100%;
  }
  .l_header.z_search-open .m_search .input {
    width: calc(100% - 120px);
  }
}
ul.m-pc >li>a {
  color: inherit;
  border-bottom: 2px solid transparent;
}
ul.m-pc >li>a:active,
ul.m-pc >li>a.active {
  border-bottom: 2px solid #3dd9b6;
}
ul.m-pc li:hover >ul.list-v,
ul.list-v li:hover >ul.list-v {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
}
ul.nav-list-h {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: -ms-flexbox /* TWEENER - IE 10 */;
  display: -webkit-flex /* NEW - Chrome */;
  display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
  display: flex;
  align-items: stretch;
}
ul.nav-list-h>li {
  position: relative;
  justify-content: center;
  -webkit-justify-content: center;
  -khtml-justify-content: center;
  -moz-justify-content: center;
  -o-justify-content: center;
  -ms-justify-content: center;
  height: 100%;
  line-height: 2.4;
  border-radius: 4px;
  -webkit-border-radius: 4px;
}
ul.nav-list-h>li >a {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-weight: 600;
}
ul.list-v {
  z-index: 1;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  position: absolute;
  background: var(--color-card);
  box-shadow: 0 2px 4px 0px rgba(0,0,0,0.08), 0 4px 8px 0px rgba(0,0,0,0.08), 0 8px 16px 0px rgba(0,0,0,0.08);
  -webkit-box-shadow: 0 2px 4px 0px rgba(0,0,0,0.08), 0 4px 8px 0px rgba(0,0,0,0.08), 0 8px 16px 0px rgba(0,0,0,0.08);
  margin-top: -6px;
  border-radius: 4px;
  -webkit-border-radius: 4px;
  padding: 8px 0;
}
ul.list-v.show {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
}
ul.list-v hr {
  margin-top: 8px;
  margin-bottom: 8px;
}
ul.list-v >li {
  white-space: nowrap;
  word-break: keep-all;
}
ul.list-v >li.header {
  font-size: 0.78125rem;
  font-weight: bold;
  line-height: 2em;
  color: var(--color-meta);
  margin: 8px 16px 4px;
}
ul.list-v >li.header i {
  margin-right: 8px;
}
ul.list-v >li ul {
  margin-left: 0;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  margin-top: -40px;
}
ul.list-v .aplayer-container {
  min-height: 64px;
  padding: 6px 16px;
}
ul.list-v >li>a {
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  color: var(--color-list);
  font-size: 0.875rem;
  font-weight: bold;
  line-height: 36px;
  padding: 0 20px 0 16px;
  text-overflow: ellipsis;
  margin: 0 4px;
  border-radius: 4px;
  -webkit-border-radius: 4px;
}
@media screen and (max-width: 1024px) {
  ul.list-v >li>a {
    line-height: 40px;
  }
}
ul.list-v >li>a >i {
  margin-right: 8px;
}
ul.list-v >li>a:active,
ul.list-v >li>a.active {
  color: var(--color-list-hl);
}
ul.list-v >li>a:hover {
  color: var(--color-list-hl);
  background: var(--color-site-bg);
}
.l_header .menu >ul>li>a {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: block;
  padding: 0 8px;
}
.l_header .menu >ul>li>a >i {
  margin-right: 4px;
}
.l_header ul.nav-list-h>li {
  color: var(--color-list);
  line-height: 64px;
}
.l_header ul.nav-list-h>li >a {
  max-height: 64px;
  overflow: hidden;
  color: inherit;
}
.l_header ul.nav-list-h>li >a:active,
.l_header ul.nav-list-h>li >a.active {
  color: #3dd9b6;
}
.l_header ul.nav-list-h>li:hover>a {
  color: var(--color-list-hl);
}
.l_header ul.nav-list-h>li i.music {
  animation: rotate-effect 1.5s linear infinite;
  -webkit-animation: rotate-effect 1.5s linear infinite;
  -khtml-animation: rotate-effect 1.5s linear infinite;
  -moz-animation: rotate-effect 1.5s linear infinite;
  -o-animation: rotate-effect 1.5s linear infinite;
  -ms-animation: rotate-effect 1.5s linear infinite;
}
@-moz-keyframes rotate-effect {
  0% {
    transform: rotate(0);
    -webkit-transform: rotate(0);
    -khtml-transform: rotate(0);
    -moz-transform: rotate(0);
    -o-transform: rotate(0);
    -ms-transform: rotate(0);
  }
  25% {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -khtml-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
    -webkit-transform: rotate(180deg);
    -khtml-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    -ms-transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -khtml-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -khtml-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
  }
}
@-webkit-keyframes rotate-effect {
  0% {
    transform: rotate(0);
    -webkit-transform: rotate(0);
    -khtml-transform: rotate(0);
    -moz-transform: rotate(0);
    -o-transform: rotate(0);
    -ms-transform: rotate(0);
  }
  25% {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -khtml-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
    -webkit-transform: rotate(180deg);
    -khtml-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    -ms-transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -khtml-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -khtml-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
  }
}
@-o-keyframes rotate-effect {
  0% {
    transform: rotate(0);
    -webkit-transform: rotate(0);
    -khtml-transform: rotate(0);
    -moz-transform: rotate(0);
    -o-transform: rotate(0);
    -ms-transform: rotate(0);
  }
  25% {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -khtml-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
    -webkit-transform: rotate(180deg);
    -khtml-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    -ms-transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -khtml-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -khtml-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
  }
}
@keyframes rotate-effect {
  0% {
    transform: rotate(0);
    -webkit-transform: rotate(0);
    -khtml-transform: rotate(0);
    -moz-transform: rotate(0);
    -o-transform: rotate(0);
    -ms-transform: rotate(0);
  }
  25% {
    transform: rotate(90deg);
    -webkit-transform: rotate(90deg);
    -khtml-transform: rotate(90deg);
    -moz-transform: rotate(90deg);
    -o-transform: rotate(90deg);
    -ms-transform: rotate(90deg);
  }
  50% {
    transform: rotate(180deg);
    -webkit-transform: rotate(180deg);
    -khtml-transform: rotate(180deg);
    -moz-transform: rotate(180deg);
    -o-transform: rotate(180deg);
    -ms-transform: rotate(180deg);
  }
  75% {
    transform: rotate(270deg);
    -webkit-transform: rotate(270deg);
    -khtml-transform: rotate(270deg);
    -moz-transform: rotate(270deg);
    -o-transform: rotate(270deg);
    -ms-transform: rotate(270deg);
  }
  100% {
    transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -khtml-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -o-transform: rotate(360deg);
    -ms-transform: rotate(360deg);
  }
}
.menu-phone li ul.list-v {
  right: calc(100% - 0.5 * 16px);
}
.menu-phone li ul.list-v ul {
  right: calc(100% - 0.5 * 16px);
}
#wrapper {
  max-width: 1080px;
  margin: auto;
}
@media screen and (min-width: 2048px) {
  #wrapper {
    max-width: 55vw;
  }
}
#wrapper .menu {
  -webkit-box-flex: 1;
  -moz-box-flex: 1;
  -webkit-flex: 1 1;
  -ms-flex: 1 1;
  flex: 1 1;
  margin: 0 16px 0 0;
}
#wrapper .menu .list-v ul {
  left: calc(100% - 0.5 * 16px);
}
.menu-phone {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  margin-top: 16px;
  right: 8px;
  transition: all 0.28s ease;
  -webkit-transition: all 0.28s ease;
  -khtml-transition: all 0.28s ease;
  -moz-transition: all 0.28s ease;
  -o-transition: all 0.28s ease;
  -ms-transition: all 0.28s ease;
}
.menu-phone ul {
  right: calc(100% - 0.5 * 16px);
}
@media screen and (max-width: 500px) {
  .menu-phone {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: block;
  }
}
.l_header {
  max-width: 65vw;
  left: calc((100% - 65vw) * 0.5);
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}
@media screen and (max-width: 2048px) {
  .l_header {
    max-width: 1112px;
    left: calc((100% - 1112px) * 0.5);
  }
}
@media screen and (max-width: 1112px) {
  .l_header {
    left: 0;
    border-radius: 0;
    -webkit-border-radius: 0;
    max-width: 100%;
  }
}
@media screen and (max-width: 500px) {
  .l_header .container {
    margin-left: 0;
    margin-right: 0;
  }
  .l_header #wrapper .nav-main .title {
    padding-left: 16px;
    padding-right: 16px;
  }
  .l_header #wrapper .nav-sub {
    width: 100%;
  }
  .l_header #wrapper .nav-sub .title {
    overflow-y: scroll;
    margin-top: 2px;
    padding: 8px 16px;
  }
  .l_header #wrapper .switcher {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: -ms-flexbox /* TWEENER - IE 10 */;
    display: -webkit-flex /* NEW - Chrome */;
    display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
    display: flex;
    margin-right: 8px;
  }
  .l_header .menu {
    display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
    display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
    display: none;
  }
}
@media screen and (max-width: 500px) {
  .list-v li {
    max-width: 270px;
  }
}
#u-search {
  display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
  display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  padding: 60px 20px;
  z-index: 1001;
}
@media screen and (max-width: 680px) {
  #u-search {
    padding: 0px;
  }
}

  </style>
  <link rel="stylesheet" href="/css/style.css" media="print" onload="this.media='all';this.onload=null">
  <noscript><link rel="stylesheet" href="/css/style.css"></noscript>
  
<script>
if (/*@cc_on!@*/false || (!!window.MSInputMethodContext && !!document.documentMode))
    document.write(
	'<style>'+
		'html{'+
			'overflow-x: hidden !important;'+
			'overflow-y: hidden !important;'+
		'}'+
		'.kill-ie{'+
			'text-align:center;'+
			'height: 100%;'+
			'margin-top: 15%;'+
			'margin-bottom: 5500%;'+
		'}'+
    '.kill-t{'+
      'font-size: 2rem;'+
    '}'+
    '.kill-c{'+
      'font-size: 1.2rem;'+
    '}'+
		'#l_header,#l_body{'+
			'display: none;'+
		'}'+
	'</style>'+
    '<div class="kill-ie">'+
        `<span class="kill-t"><b>Sorry, your browser cannot access this site</b></span><br/>`+
        `<span class="kill-c">Microsoft has terminated support for Internet Explorer (IE) 10 and earlier versions in 2016. <br/>There are great security risks to continue using it. Please use contemporary mainstream browsers to access.</span><br/>`+
        `<a target="_blank" rel="noopener" href="https://blogs.windows.com/windowsexperience/2021/05/19/the-future-of-internet-explorer-on-windows-10-is-in-microsoft-edge/"><strong>Learn more ></strong></a>`+
    '</div>');
</script>


<noscript>
	<style>
		html{
			overflow-x: hidden !important;
			overflow-y: hidden !important;
		}
		.kill-noscript{
			text-align:center;
			height: 100%;
			margin-top: 15%;
			margin-bottom: 5500%;
		}
    .kill-t{
      font-size: 2rem;
    }
    .kill-c{
      font-size: 1.2rem;
    }
		#l_header,#l_body{
			display: none;
		}
	</style>
    <div class="kill-noscript">
        <span class="kill-t"><b>Sorry, your browser cannot access this site</b></span><br/>
        <span class="kill-c">This page requires browser support (enable) JavaScript</span><br/>
        <a target="_blank" rel="noopener" href="https://www.baidu.com/s?wd=启用JavaScript"><strong>Learn more ></strong></a>
    </div>
</noscript>


  <script>
  /************这个文件存放不需要重载的全局变量和全局函数*********/
  window.volantis = {}; // volantis 全局变量
  volantis.debug = "env"; // 调试模式
  volantis.dom = {}; // 页面Dom see: /source/js/app.js etc.

  volantis.GLOBAL_CONFIG ={
    debug: "env",
    cdn: {"js":{"app":"/js/app.js","parallax":"/js/plugins/parallax.js","rightMenu":"/js/plugins/rightMenu.js","rightMenus":"/js/plugins/rightMenus.js","sites":"/js/plugins/tags/sites.js","friends":"/js/plugins/tags/friends.js","contributors":"/js/plugins/tags/contributors.js","search":"/js/search/hexo.js"},"css":{"style":"/css/style.css"}},
    default: {"avatar":"https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/avatar/round/3442075.svg","link":"https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/link/8f277b4ee0ecd.svg","cover":"https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/cover/76b86c0226ffd.svg","image":"https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/image/2659360.svg"},
    lastupdate: new Date(1708699590610),
    sidebar: {
      for_page: ["blogger","category","tagcloud","donate"],
      for_post: ["toc"],
      webinfo: {
        lastupd: {
          enable: true,
          friendlyShow: true
        },
        runtime: {
          data: "2020/01/01",
          unit: "天"
        }
      }
    },
    plugins: {
      message: {"enable":true,"css":"https://unpkg.com/volantis-static@0.0.1654736714924/libs/izitoast/dist/css/iziToast.min.css","js":"https://unpkg.com/volantis-static@0.0.1654736714924/libs/izitoast/dist/js/iziToast.min.js","icon":{"default":"fa-solid fa-info-circle light-blue","quection":"fa-solid fa-question-circle light-blue"},"time":{"default":5000,"quection":20000},"position":"topRight","transitionIn":"bounceInLeft","transitionOut":"fadeOutRight","titleColor":"var(--color-text)","messageColor":"var(--color-text)","backgroundColor":"var(--color-card)","zindex":2147483647,"copyright":{"enable":true,"title":"知识共享许可协议","message":"请遵守 CC BY-NC-SA 4.0 协议。","icon":"far fa-copyright light-blue"},"aplayer":{"enable":true,"play":"fa-solid fa-play","pause":"fa-solid fa-pause"},"rightmenu":{"enable":true,"notice":true}},
      fancybox: {"css":"https://unpkg.com/volantis-static@0.0.1654736714924/libs/@fancyapps/ui/dist/fancybox.css","js":"https://unpkg.com/volantis-static@0.0.1654736714924/libs/@fancyapps/ui/dist/fancybox.umd.js"},
      
      
      
    }
  }

  /******************** volantis.EventListener ********************************/
  // 事件监听器 see: /source/js/app.js
  volantis.EventListener = {}
  // 这里存放pjax切换页面时将被移除的事件监听器
  volantis.EventListener.list = []
  //构造方法
  function volantisEventListener(type, f, ele) {
    this.type = type
    this.f = f
    this.ele = ele
  }
  // 移除事件监听器
  volantis.EventListener.remove = () => {
    volantis.EventListener.list.forEach(function (i) {
      i.ele.removeEventListener(i.type, i.f, false)
    })
    volantis.EventListener.list = []
  }
  /******************** volantis.dom.$ ********************************/
  // 注：这里没有选择器，也没有forEach一次只处理一个dom，这里重新封装主题常用的dom方法，返回的是dom对象，对象包含了以下方法，同时保留dom的原生API
  function volantisDom(ele) {
    if (!ele) ele = document.createElement("div")
    this.ele = ele;
    // ==============================================================
    this.ele.find = (c) => {
      let q = this.ele.querySelector(c)
      if (q)
        return new volantisDom(q)
    }
    // ==============================================================
    this.ele.hasClass = (c) => {
      return this.ele.className.match(new RegExp('(\\s|^)' + c + '(\\s|$)'));
    }
    this.ele.addClass = (c) => {
      this.ele.classList.add(c);
      return this.ele
    }
    this.ele.removeClass = (c) => {
      this.ele.classList.remove(c);
      return this.ele
    }
    this.ele.toggleClass = (c) => {
      if (this.ele.hasClass(c)) {
        this.ele.removeClass(c)
      } else {
        this.ele.addClass(c)
      }
      return this.ele
    }
    // ==============================================================
    // 参数 r 为 true 表示pjax切换页面时事件监听器将被移除，false不移除
    this.ele.on = (c, f, r = 1) => {
      this.ele.addEventListener(c, f, false)
      if (r) {
        volantis.EventListener.list.push(new volantisEventListener(c, f, this.ele))
      }
      return this.ele
    }
    this.ele.click = (f, r) => {
      this.ele.on("click", f, r)
      return this.ele
    }
    this.ele.scroll = (f, r) => {
      this.ele.on("scroll", f, r)
      return this.ele
    }
    // ==============================================================
    this.ele.html = (c) => {
      // if(c=== undefined){
      //   return this.ele.innerHTML
      // }else{
      this.ele.innerHTML = c
      return this.ele
      // }
    }
    // ==============================================================
    this.ele.hide = (c) => {
      this.ele.style.display = "none"
      return this.ele
    }
    this.ele.show = (c) => {
      this.ele.style.display = "block"
      return this.ele
    }
    // ==============================================================
    return this.ele
  }
  volantis.dom.$ = (ele) => {
    return !!ele ? new volantisDom(ele) : null;
  }
  /******************** RunItem ********************************/
  function RunItem() {
    this.list = []; // 存放回调函数
    this.start = () => {
      for (var i = 0; i < this.list.length; i++) {
        this.list[i].run();
      }
    };
    this.push = (fn, name, setRequestAnimationFrame = true) => {
      let myfn = fn
      if (setRequestAnimationFrame) {
        myfn = ()=>{
          volantis.requestAnimationFrame(fn)
        }
      }
      var f = new Item(myfn, name);
      this.list.push(f);
    };
    this.remove = (name) =>{
      for (let index = 0; index < this.list.length; index++) {
        const e = this.list[index];
        if (e.name == name) {
          this.list.splice(index,1);
        }
      }
    }
    // 构造一个可以run的对象
    function Item(fn, name) {
      // 函数名称
      this.name = name || fn.name;
      // run方法
      this.run = () => {
        try {
          fn()
        } catch (error) {
          console.log(error);
        }
      };
    }
  }
  /******************** Pjax ********************************/
  // /layout/_plugins/pjax/index.ejs
  // volantis.pjax.send(callBack[,"callBackName"]) 传入pjax:send回调函数
  // volantis.pjax.push(callBack[,"callBackName"]) 传入pjax:complete回调函数
  // volantis.pjax.error(callBack[,"callBackName"]) 传入pjax:error回调函数
  volantis.pjax = {};
  volantis.pjax.method = {
    complete: new RunItem(),
    error: new RunItem(),
    send: new RunItem(),
  };
  volantis.pjax = Object.assign(volantis.pjax, {
    push: volantis.pjax.method.complete.push,
    error: volantis.pjax.method.error.push,
    send: volantis.pjax.method.send.push,
  });
  /******************** RightMenu ********************************/
  // volantis.rightmenu.handle(callBack[,"callBackName"]) 外部菜单项控制
  // 可在 volantis.mouseEvent 处获取右键事件
  volantis.rightmenu = {};
  volantis.rightmenu.method = {
    handle: new RunItem(),
  }
  volantis.rightmenu = Object.assign(volantis.rightmenu, {
    handle: volantis.rightmenu.method.handle.push,
  });
  /********************  Dark Mode  ********************************/
  // /layout/_partial/scripts/darkmode.ejs
  // volantis.dark.mode 当前模式 dark or light
  // volantis.dark.toggle() 暗黑模式触发器
  // volantis.dark.push(callBack[,"callBackName"]) 传入触发器回调函数
  volantis.dark = {};
  volantis.dark.method = {
    toggle: new RunItem(),
  };
  volantis.dark = Object.assign(volantis.dark, {
    push: volantis.dark.method.toggle.push,
  });
  /********************  Message  ********************************/
  // VolantisApp.message
  /********************  isMobile  ********************************/
  // /source/js/app.js
  // volantis.isMobile
  // volantis.isMobileOld
  /********************脚本动态加载函数********************************/
  // volantis.js(src, cb)  cb 可以传入onload回调函数 或者 JSON对象 例如: volantis.js("src", ()=>{}) 或 volantis.js("src", {defer:true,onload:()=>{}})
  // volantis.css(src)

  // 返回Promise对象，如下方法同步加载资源，这利于处理文件资源之间的依赖关系，例如：APlayer 需要在 MetingJS 之前加载
  // (async () => {
  //     await volantis.js("...theme.plugins.aplayer.js.aplayer...")
  //     await volantis.js("...theme.plugins.aplayer.js.meting...")
  // })();

  // 已经加入了setTimeout
  volantis.js = (src, cb) => {
    return new Promise(resolve => {
      setTimeout(function () {
        var HEAD = document.getElementsByTagName("head")[0] || document.documentElement;
        var script = document.createElement("script");
        script.setAttribute("type", "text/javascript");
        if (cb) {
          if (JSON.stringify(cb)) {
            for (let p in cb) {
              if (p == "onload") {
                script[p] = () => {
                  cb[p]()
                  resolve()
                }
              } else {
                script[p] = cb[p]
                script.onload = resolve
              }
            }
          } else {
            script.onload = () => {
              cb()
              resolve()
            };
          }
        } else {
          script.onload = resolve
        }
        script.setAttribute("src", src);
        HEAD.appendChild(script);
      });
    });
  }
  volantis.css = (src) => {
    return new Promise(resolve => {
      setTimeout(function () {
        var link = document.createElement('link');
        link.rel = "stylesheet";
        link.href = src;
        link.onload = resolve;
        document.getElementsByTagName("head")[0].appendChild(link);
      });
    });
  }
  /********************按需加载的插件********************************/
  // volantis.import.jQuery().then(()=>{})
  volantis.import = {
    jQuery: () => {
      if (typeof jQuery == "undefined") {
        return volantis.js("https://unpkg.com/volantis-static@0.0.1654736714924/libs/jquery/dist/jquery.min.js")
      } else {
        return new Promise(resolve => {
          resolve()
        });
      }
    }
  }
  /********************** requestAnimationFrame ********************************/
  // 1、requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来，在一次重绘或回流中就完成，并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率，一般来说，这个频率为每秒60帧。
  // 2、在隐藏或不可见的元素中，requestAnimationFrame 将不会进行重绘或回流，这当然就意味着更少的的 cpu，gpu 和内存使用量。
  volantis.requestAnimationFrame = (fn)=>{
    if (!window.requestAnimationFrame) {
      window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame;
    }
    window.requestAnimationFrame(fn)
  }
  /************************ layoutHelper *****************************************/
  volantis.layoutHelper = (helper, html, opt)=>{
    opt = Object.assign({clean:false, pjax:true}, opt)
    function myhelper(helper, html, clean) {
      volantis.tempDiv = document.createElement("div");
      volantis.tempDiv.innerHTML = html;
      let layoutHelper = document.querySelector("#layoutHelper-"+helper)
      if (layoutHelper) {
        if (clean) {
          layoutHelper.innerHTML = ""
        }
        layoutHelper.append(volantis.tempDiv);
      }
    }
    myhelper(helper, html, opt.clean)
    if (opt.pjax) {
      volantis.pjax.push(()=>{
        myhelper(helper, html, opt.clean)
      },"layoutHelper-"+helper)
    }
  }
  /****************************** 滚动事件处理 ****************************************/
  volantis.scroll = {
    engine: new RunItem(),
    unengine: new RunItem(),
  };
  volantis.scroll = Object.assign(volantis.scroll, {
    push: volantis.scroll.engine.push,
  });
  // 滚动条距离顶部的距离
  volantis.scroll.getScrollTop = () =>{
    let scrollPos;
    if (window.pageYOffset) {
      scrollPos = window.pageYOffset;
    } else if (document.compatMode && document.compatMode != 'BackCompat') {
      scrollPos = document.documentElement.scrollTop;
    } else if (document.body) {
      scrollPos = document.body.scrollTop;
    }
    return scrollPos;
  }
  // 使用 requestAnimationFrame 处理滚动事件
  // `volantis.scroll.del` 中存储了一个数值, 该数值检测一定时间间隔内滚动条滚动的位移, 数值的检测频率是浏览器的刷新频率. 数值为正数时, 表示向下滚动. 数值为负数时, 表示向上滚动.
  volantis.scroll.handleScrollEvents = () => {
    volantis.scroll.lastScrollTop = volantis.scroll.getScrollTop()
    function loop() {
      const scrollTop = volantis.scroll.getScrollTop();
      if (volantis.scroll.lastScrollTop !== scrollTop) {
        volantis.scroll.del = scrollTop - volantis.scroll.lastScrollTop;
        volantis.scroll.lastScrollTop = scrollTop;
        // if (volantis.scroll.del > 0) {
        //   console.log("向下滚动");
        // } else {
        //   console.log("向上滚动");
        // }
        // 注销过期的unengine未滚动事件
        volantis.scroll.unengine.list=[]
        volantis.scroll.engine.start();
      }else{
        volantis.scroll.unengine.start();
      }
      volantis.requestAnimationFrame(loop)
    }
    volantis.requestAnimationFrame(loop)
  }
  volantis.scroll.handleScrollEvents()
  volantis.scroll.ele = null;
  // 触发页面滚动至目标元素位置
  volantis.scroll.to = (ele, option = {}) => {
    if (!ele) return;
    volantis.scroll.ele = ele;
    // 默认配置
    opt = {
      top: ele.getBoundingClientRect().top + document.documentElement.scrollTop,
      behavior: "smooth"
    }
    // 定义配置
    if ("top" in option) {
      opt.top = option.top
    }
    if ("behavior" in option) {
      opt.behavior = option.behavior
    }
    if ("addTop" in option) {
      opt.top += option.addTop
    }
    if (!("observerDic" in option)) {
      option.observerDic = 100
    }
    // 滚动
    window.scrollTo(opt);
    // 监视器
    // 监视并矫正元素滚动到指定位置
    // 用于处理 lazyload 引起的 cls 导致的定位失败问题
    // option.observer = false
    if (option.observer) {
      setTimeout(() => {
        if (volantis.scroll.ele != ele) {
          return
        }
        volantis.scroll.unengine.push(() => {
          let me = ele.getBoundingClientRect().top
          if(!(me >= -option.observerDic && me <= option.observerDic)){
            volantis.scroll.to(ele, option)
          }
          volantis.scroll.unengine.remove("unengineObserver")
        },"unengineObserver")
      },1000)
    }
  }
  /********************** Content Visibility ********************************/
  // 见 source/css/first.styl 如果遇到任何问题 删除 .post-story 即可
  // 一个元素被声明 content-visibility 属性后 如果元素不在 viewport 中 浏览器不会计算其后代元素样式和属性 从而节省 Style & Layout 耗时
  // content-visibility 的副作用: 锚点失效 等等(实验初期 暂不明确), 使用此方法清除样式
  volantis.cleanContentVisibility = ()=>{
    if (document.querySelector(".post-story")) {
      console.log("cleanContentVisibility");
      document.querySelectorAll(".post-story").forEach(e=>{
        e.classList.remove("post-story")
      })
    }
  }
  /******************************************************************************/
  /******************************************************************************/
  /******************************************************************************/
  //图像加载出错时的处理
  function errorImgAvatar(img) {
    img.src = "https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/avatar/round/3442075.svg";
    img.onerror = null;
  }
  function errorImgCover(img) {
    img.src = "https://unpkg.com/volantis-static@0.0.1654736714924/media/placeholder/cover/76b86c0226ffd.svg";
    img.onerror = null;
  }
  /******************************************************************************/
</script>

  <!-- import head_end begin -->
  <!-- import head_end end -->
  <!-- Custom Files headEnd begin-->
  
  <!-- Custom Files headEnd end-->
  <!-- front-matter head_end begin -->
  <!-- front-matter head_end end -->
</head>
  <body itemscope itemtype="http://schema.org/WebPage">
    <!-- import body_begin begin-->
    <!-- import body_begin end-->
    <!-- Custom Files bodyBegin begin-->
    
    <!-- Custom Files bodyBegin end-->
    <!-- front-matter body_begin begin -->
    <!-- front-matter body_begin end -->
    <header itemscope itemtype="http://schema.org/WPHeader" id="l_header" class="l_header auto shadow floatable blur show" style='opacity: 0' >
  <div class='container'>
  <div id='wrapper'>
    <div class='nav-sub'>
      <p class="title"></p>
      <ul class='switcher nav-list-h m-phone' id="pjax-header-nav-list">
        <li><a id="s-comment" class="fa-solid fa-comments fa-fw" target="_self"  href="/" onclick="return false;" title="comment"></a></li>
        
          <li><a id="s-toc" class="s-toc fa-solid fa-list fa-fw" target="_self"  href="/" onclick="return false;" title="toc"></a></li>
        
      </ul>
    </div>
		<div class="nav-main">
      
        
        <a class="title flat-box" target="_self" href='/'>
          
            <img no-lazy class='logo' src='https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/Logo-NavBar@3x.png'/>
          
          
          
        </a>
      

			<div class='menu navigation'>
				<ul class='nav-list-h m-pc'>
          
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/" title="博客"
                  
                  
                  
                    active-action="action-home"
                  >
                  <i class='fa-solid fa-rss fa-fw'></i>博客
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/categories/" title="分类"
                  
                  
                  
                    active-action="action-categories"
                  >
                  <i class='fa-solid fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/tags/" title="标签"
                  
                  
                  
                    active-action="action-tags"
                  >
                  <i class='fa-solid fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/archives/" title="归档"
                  
                  
                  
                    active-action="action-archives"
                  >
                  <i class='fa-solid fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/friends/" title="友链"
                  
                  
                  
                    active-action="action-friends"
                  >
                  <i class='fa-solid fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/about/" title="关于"
                  
                  
                  
                    active-action="action-about"
                  >
                  <i class='fa-solid fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
          
				</ul>
			</div>
      
      <div class="m_search">
        <form name="searchform" class="form u-search-form">
          <i class="icon fa-solid fa-search fa-fw"></i>
          <input type="text" class="input u-search-input" placeholder="Search..." />
        </form>
      </div>
      

			<ul class='switcher nav-list-h m-phone'>
				
					<li><a class="s-search fa-solid fa-search fa-fw" target="_self" href="/" onclick="return false;" title="search"></a></li>
				
				<li>
          <a class="s-menu fa-solid fa-bars fa-fw" target="_self" href="/" onclick="return false;" title="menu"></a>
          <ul class="menu-phone list-v navigation white-box">
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/" title="博客"
                  
                  
                  
                    active-action="action-home"
                  >
                  <i class='fa-solid fa-rss fa-fw'></i>博客
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/categories/" title="分类"
                  
                  
                  
                    active-action="action-categories"
                  >
                  <i class='fa-solid fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/tags/" title="标签"
                  
                  
                  
                    active-action="action-tags"
                  >
                  <i class='fa-solid fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/archives/" title="归档"
                  
                  
                  
                    active-action="action-archives"
                  >
                  <i class='fa-solid fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/friends/" title="友链"
                  
                  
                  
                    active-action="action-friends"
                  >
                  <i class='fa-solid fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover"
                href="/about/" title="关于"
                  
                  
                  
                    active-action="action-about"
                  >
                  <i class='fa-solid fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
            
          </ul>
        </li>
			</ul>

      <!-- Custom Files header begin -->
      
      <!-- Custom Files header end -->
		</div>
	</div>
  </div>
</header>

    <div id="l_body">
      <div id="l_cover">
  
    
      <!-- see: /layout/_partial/scripts/_ctrl/coverCtrl.ejs -->
      <div id="none" class='cover-wrapper post dock' style="display: none;">
        
  <div class='cover-bg lazyload placeholder' data-bg="https://gcore.jsdelivr.net/gh/MHG-LAB/cron@gh-pages/bing/bing.jpg"></div>

<div class='cover-body'>
  <div class='top'>
    
    
      <p class="title">Volantis</p>
    
    
  </div>
  <div class='bottom'>
    <div class='menu navigation'>
      <div class='list-h'>
        
          
            <a href="/v4/getting-started/"
              
              
              active-action="action-v4getting-started">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f5c3.svg'><p>文档</p>
            </a>
          
            <a href="/faqs/"
              
              
              active-action="action-faqs">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f516.svg'><p>帮助</p>
            </a>
          
            <a href="/examples/"
              
              
              active-action="action-examples">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f396.svg'><p>示例</p>
            </a>
          
            <a href="/contributors/"
              
              
              active-action="action-contributors">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f389.svg'><p>社区</p>
            </a>
          
            <a href="/archives/"
              
              
              active-action="action-archives">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f4f0.svg'><p>博客</p>
            </a>
          
            <a target="_blank" rel="noopener" href="https://github.com/volantis-x/hexo-theme-volantis/"
              
              
              active-action="action-https:githubcomvolantis-xhexo-theme-volantis">
              <img src='https://unpkg.com/volantis-static@0.0.1654736714924/media/twemoji/assets/svg/1f9ec.svg'><p>源码</p>
            </a>
          
        
      </div>
    </div>
  </div>
</div>

        <div id="scroll-down" style="display: none;"><i class="fa fa-chevron-down scroll-down-effects"></i></div>
      </div>
    
  
</div>

      <div id="safearea">
        <div class="body-wrapper">
          
<div id="l_main" class=''>
  <article itemscope itemtype="http://schema.org/Article" class="article post white-box reveal md shadow floatable blur article-type-post" id="post" itemscope itemprop="blogPost">
  <link itemprop="mainEntityOfPage" href="http://8.219.11.28/2024/02/23/单体-JSP/">
  <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
    <meta itemprop="name" content="欢迎来到我的个人博客~">
  </span>
  <span hidden itemprop="post" itemscope itemtype="http://schema.org/Post">
    <meta itemprop="name" content="欢迎来到我的个人博客~">
    <meta itemprop="description" content="这些技术大部分是自己总结的，非官方">
  </span>
  


  
    <span hidden>
      <meta itemprop="image" content="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png">
    </span>
  
  <div class="article-meta" id="top">
    
    
    
      <span hidden itemprop="name headline">
        
      </span>
    
  </div>


  <div id="layoutHelper-page-plugins"></div>
  <div id="post-body" itemprop="articleBody">
    <h2 id="一、JSP概述"><a href="#一、JSP概述" class="headerlink" title="一、JSP概述"></a>一、JSP概述</h2><h3 id="1-1-Servlet使用的不足"><a href="#1-1-Servlet使用的不足" class="headerlink" title="1.1 Servlet使用的不足"></a>1.1 Servlet使用的不足</h3><blockquote>
<p>Servlet是一个动态网页技术，客户端通过请求Servlet类可以相应给客户端一个动态网页，但是Servlet在使用过程中有什么不足之处呢？</p>
<ul>
<li><p>开发方式麻烦：继承HttpServlet父类、重写doGet&#x2F;doPost、Servlet配置</p>
</li>
<li><p>项目更新麻烦：Servlet类中的代码发生改变，需要重新编译、部署、启动Tomcat</p>
</li>
<li><p>网页呈现复杂：需要进行HTML标签拼接，同时要通过输出流逐行打印</p>
</li>
<li><p>协同开发困难：UI负责页面美化，但是页面是由Servlet类提供，如果UI不懂Java、则不能完成Servlet响应的页面的优化</p>
</li>
</ul>
</blockquote>
<h3 id="1-2-JSP简介"><a href="#1-2-JSP简介" class="headerlink" title="1.2 JSP简介"></a>1.2 JSP简介</h3><blockquote>
<p>JSP (Java Server Page)  基于Servlet技术的、运行在服务器之上、支持Java语言的动态网页技术。</p>
</blockquote>
<p>背景：JSP简化了Servlet的设计，采用在HTML标签中嵌套代码的形式进行动态网页的呈现，用于高效开发web应用的动态网页。</p>
<p>作用：替换显示页面部分的Servlet（使用<code>*.jsp</code>网页文件替换<code>*PageServlet.java</code>类）</p>
<h2 id="二、JSP入门案例"><a href="#二、JSP入门案例" class="headerlink" title="二、JSP入门案例"></a>二、JSP入门案例</h2><p>架构模式:</p>
<table>
<thead>
<tr>
<th>JSP入门案例流程：</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211115114112662.png" class="lazyload" data-srcset="/imgs/image-20211115114112662.png" srcset="" alt="image-20211115114112662"></td>
</tr>
</tbody></table>
<h3 id="2-1-案例准备"><a href="#2-1-案例准备" class="headerlink" title="2.1 案例准备"></a>2.1 案例准备</h3><h4 id="2-1-1-创建数据库数据表"><a href="#2-1-1-创建数据库数据表" class="headerlink" title="2.1.1 创建数据库数据表"></a>2.1.1 创建数据库数据表</h4><ul>
<li>创建数据库 <code>db_jsp</code></li>
<li>创建图书信息表</li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> books(</span><br><span class="line">   book_id <span class="type">char</span>(<span class="number">6</span>) <span class="keyword">primary</span> key,</span><br><span class="line">	 book_name <span class="type">varchar</span>(<span class="number">50</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">	 book_author <span class="type">varchar</span>(<span class="number">20</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">	 book_price <span class="type">DECIMAL</span>(<span class="number">10</span>,<span class="number">2</span>),</span><br><span class="line">	 book_img_path <span class="type">varchar</span>(<span class="number">100</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">	 book_desc <span class="type">varchar</span>(<span class="number">200</span>),</span><br><span class="line">	 book_type <span class="type">int</span> <span class="keyword">not</span> <span class="keyword">null</span> </span><br><span class="line">);</span><br></pre></td></tr></table></figure>

<h4 id="2-1-2-创建web项目"><a href="#2-1-2-创建web项目" class="headerlink" title="2.1.2 创建web项目"></a>2.1.2 创建web项目</h4><p>JSP必须依赖于服务器运行，因此只能在web应用中使用JSP技术</p>
<p>web项目名称<code>jsp-demo1</code></p>
<h4 id="2-1-3-完成JDBC准备"><a href="#2-1-3-完成JDBC准备" class="headerlink" title="2.1.3 完成JDBC准备"></a>2.1.3 完成JDBC准备</h4><ul>
<li><p>导入jar包：mysql驱动、druid.jar、apache commons dbutils</p>
</li>
<li><p>创建<code>com.qfedu.jsp.utils</code>包，在包中创建<code>druid.properties</code>文件配置连接池参数</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 数据库连接信息</span></span><br><span class="line"><span class="attr">driverClassName</span>=<span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line"><span class="attr">url</span>=<span class="string">jdbc:mysql://localhost:3306/db_jsp?characterEncoding=utf8</span></span><br><span class="line"><span class="attr">username</span>=<span class="string">root</span></span><br><span class="line"><span class="attr">password</span>=<span class="string">@QFedu123</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 连接池属性</span></span><br><span class="line"><span class="comment"># 连接池的初始化连接数&lt;创建数据库连接池时默认初始化的连接的个数&gt;</span></span><br><span class="line"><span class="attr">initialSize</span>=<span class="string">10</span></span><br><span class="line"><span class="comment"># 连接池的最大连接数</span></span><br><span class="line"><span class="attr">maxActive</span>=<span class="string">50</span></span><br><span class="line"><span class="comment"># 最小空闲连接数（当数据库连接使用率很低时，连接池中的连接会被释放一部分）</span></span><br><span class="line"><span class="attr">minIdle</span>=<span class="string">5</span></span><br><span class="line"><span class="comment"># 超时等待时间(单位：ms)</span></span><br><span class="line"><span class="attr">maxWait</span>=<span class="string">30000</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>在utils包中连接池工具类<code>DruidUtils</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.jsp.utils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.druid.pool.DruidDataSource;</span><br><span class="line"><span class="keyword">import</span> com.alibaba.druid.pool.DruidDataSourceFactory;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.sql.*;</span><br><span class="line"><span class="keyword">import</span> java.io.InputStream;</span><br><span class="line"><span class="keyword">import</span> java.sql.*;</span><br><span class="line"><span class="keyword">import</span> java.util.Properties;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 数据库连接池工具类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DruidUtils</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> DruidDataSource druidDataSource;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">InputStream</span> <span class="variable">is</span> <span class="operator">=</span> DruidUtils.class.getResourceAsStream(<span class="string">&quot;druid.properties&quot;</span>);</span><br><span class="line">            <span class="type">Properties</span> <span class="variable">properties</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Properties</span>();</span><br><span class="line">            properties.load(is);</span><br><span class="line">            druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取数据库连接池数据源对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> DataSource <span class="title function_">getDataSource</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> druidDataSource;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 从数据库连接池中获取数据库连接对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Connection <span class="title function_">getConnection</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">Connection</span> <span class="variable">connection</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            connection = druidDataSource.getConnection();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> connection;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="2-2-完成案例的数据库操作"><a href="#2-2-完成案例的数据库操作" class="headerlink" title="2.2 完成案例的数据库操作"></a>2.2 完成案例的数据库操作</h3><h4 id="2-2-1-创建实体类"><a href="#2-2-1-创建实体类" class="headerlink" title="2.2.1 创建实体类"></a>2.2.1 创建实体类</h4><ul>
<li><p>创建<code>com.qfedu.jsp.dto</code>包</p>
</li>
<li><p>创建实体类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.jsp.dto;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 图书信息实体类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Book</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String bookId;</span><br><span class="line">    <span class="keyword">private</span> String bookName;</span><br><span class="line">    <span class="keyword">private</span> String bookAuthor;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">double</span> bookPrice;</span><br><span class="line">    <span class="keyword">private</span> String bookImgPath;</span><br><span class="line">    <span class="keyword">private</span> String bookDesc;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> bookType;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="2-2-2-创建DAO类完成操作"><a href="#2-2-2-创建DAO类完成操作" class="headerlink" title="2.2.2 创建DAO类完成操作"></a>2.2.2 创建DAO类完成操作</h4><ul>
<li><p>创建<code>com.qfedu.jsp.dao</code>包</p>
</li>
<li><p>创建BookDAO类，完成查询操作</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.jsp.dao;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.qfedu.jsp.dto.Book;</span><br><span class="line"><span class="keyword">import</span> com.qfedu.jsp.utils.DruidUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.dbutils.QueryRunner;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.dbutils.handlers.BeanListHandler;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookDAO</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> List&lt;Book&gt; <span class="title function_">listBooks</span><span class="params">()</span>&#123;</span><br><span class="line">        List&lt;Book&gt; bookList = <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select book_id bookId,book_name bookName,book_author bookAuthor,book_price bookPrice,book_img_path bookImgPath,book_desc bookDesc,book_type bookType from books&quot;</span>;</span><br><span class="line">            <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">            bookList = queryRunner.query(sql, <span class="keyword">new</span> <span class="title class_">BeanListHandler</span>&lt;Book&gt;(Book.class));</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> bookList;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="2-3-JSP呈现动态网页"><a href="#2-3-JSP呈现动态网页" class="headerlink" title="2.3 JSP呈现动态网页"></a>2.3 JSP呈现动态网页</h3><h4 id="2-3-1-创建BookListServlet"><a href="#2-3-1-创建BookListServlet" class="headerlink" title="2.3.1 创建BookListServlet"></a>2.3.1 创建BookListServlet</h4><ul>
<li><p>创建BookListServlet类,接收用户请求</p>
</li>
<li><p>调用BookDAO查询图书信息，并将数据转发到 <code>book-list.jsp</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.jsp.servlets;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 接收客户端请求场、查询图书信息，将图书信息转发到一个JSP文件进行显示</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@WebServlet(&quot;/BookListServlet&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookListServlet</span> <span class="keyword">extends</span> <span class="title class_">HttpServlet</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doGet</span><span class="params">(HttpServletRequest req, HttpServletResponse resp)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        doPost(req, resp);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doPost</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        <span class="comment">//1.调用BookDAO查询图书信息</span></span><br><span class="line">        <span class="type">BookDAO</span> <span class="variable">bookDAO</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BookDAO</span>();</span><br><span class="line">        List&lt;Book&gt; bookList = bookDAO.listBooks();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.将数据转发到book-list.jsp进行动态显示</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;bookList&quot;</span>,bookList);</span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;book-list.jsp&quot;</span>).forward(request,response);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="2-3-2-创建JSP页面"><a href="#2-3-2-创建JSP页面" class="headerlink" title="2.3.2 创建JSP页面"></a>2.3.2 创建JSP页面</h4><ul>
<li><p>在项目的web目录下右键 — 新建 — JSP — 输入名称<code>book-list.jsp</code> — OK</p>
</li>
<li><p>在<code>book-list.jsp</code>进行网页界面设计（HTML+CSS+JS）</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">    &lt;head&gt;</span><br><span class="line">        &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">    &lt;/head&gt;</span><br><span class="line">    &lt;body&gt;</span><br><span class="line"></span><br><span class="line">        &lt;table width=<span class="string">&quot;80%&quot;</span> align=<span class="string">&quot;center&quot;</span> border=<span class="string">&quot;1&quot;</span> cellspacing=<span class="string">&quot;0&quot;</span>&gt;</span><br><span class="line">            &lt;caption&gt;图书信息列表&lt;/caption&gt;</span><br><span class="line">            &lt;tr&gt;</span><br><span class="line">                &lt;th&gt;图书ID&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;图书名称&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;作者&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;价格&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;封面&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;描述&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;类型&lt;/th&gt;</span><br><span class="line">            &lt;/tr&gt;</span><br><span class="line">            &lt;tr&gt;</span><br><span class="line">                &lt;td&gt;<span class="number">10001</span>&lt;/td&gt;</span><br><span class="line">                &lt;td&gt;Java&lt;/td&gt;</span><br><span class="line">                &lt;td&gt;张三&lt;/td&gt;</span><br><span class="line">                &lt;td&gt;<span class="number">11.11</span>&lt;/td&gt;</span><br><span class="line">                &lt;td&gt;files/aaa.jpg&lt;/td&gt;</span><br><span class="line">                &lt;td&gt;这本书真香&lt;/td&gt;</span><br><span class="line">                &lt;td&gt;<span class="number">1</span>&lt;/td&gt;</span><br><span class="line">            &lt;/tr&gt;</span><br><span class="line">        &lt;/table&gt;</span><br><span class="line"></span><br><span class="line">    &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="2-3-3-在JSP页面中显示动态数据"><a href="#2-3-3-在JSP页面中显示动态数据" class="headerlink" title="2.3.3 在JSP页面中显示动态数据"></a>2.3.3 在JSP页面中显示动态数据</h4><ul>
<li>在JSP页面文件中，通过Java代码接收图书信息，并遍历显示在HTML标签中</li>
</ul>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page <span class="keyword">import</span>=<span class="string">&quot;java.util.List&quot;</span> %&gt;</span><br><span class="line">&lt;%@ page <span class="keyword">import</span>=<span class="string">&quot;com.qfedu.jsp.dto.Book&quot;</span> %&gt;</span><br><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">    &lt;head&gt;</span><br><span class="line">        &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">    &lt;/head&gt;</span><br><span class="line">    &lt;body&gt;</span><br><span class="line"></span><br><span class="line">        &lt;table width=<span class="string">&quot;80%&quot;</span> align=<span class="string">&quot;center&quot;</span> border=<span class="string">&quot;1&quot;</span> cellspacing=<span class="string">&quot;0&quot;</span>&gt;</span><br><span class="line">            &lt;caption&gt;图书信息列表&lt;/caption&gt;</span><br><span class="line">            &lt;tr&gt;</span><br><span class="line">                &lt;th&gt;图书ID&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;图书名称&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;作者&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;价格&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;封面&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;描述&lt;/th&gt;</span><br><span class="line">                &lt;th&gt;类型&lt;/th&gt;</span><br><span class="line">            &lt;/tr&gt;</span><br><span class="line">            &lt;%-- 在JSP中可以写Java代码，但是代码必须写在&lt;%%&gt;符号中 --%&gt;</span><br><span class="line">            &lt;%</span><br><span class="line">            <span class="comment">//1.通过Java代码，接收BookListServlet转发时传递的 图书信息集合的数据</span></span><br><span class="line">            List&lt;Book&gt; bookList = (List&lt;Book&gt;) request.getAttribute(<span class="string">&quot;bookList&quot;</span>);</span><br><span class="line">            <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">0</span>; i&lt; bookList.size() ; i++)&#123;</span><br><span class="line">                <span class="comment">//book是java代码中的变量</span></span><br><span class="line">                <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> bookList.get(i);</span><br><span class="line">            %&gt;</span><br><span class="line">                &lt;tr&gt;</span><br><span class="line">                    &lt;%-- 如果需要将JSP中java代码的变量显示在HTML标签中，则需要使用&lt;%=attr%&gt; --%&gt;</span><br><span class="line">                    &lt;td&gt;&lt;%=book.getBookId() %&gt;&lt;/td&gt;</span><br><span class="line">                    &lt;td&gt;&lt;%=book.getBookName() %&gt;&lt;/td&gt;</span><br><span class="line">                    &lt;td&gt;&lt;%=book.getBookAuthor() %&gt;&lt;/td&gt;</span><br><span class="line">                    &lt;td&gt;&lt;%=book.getBookPrice() %&gt;&lt;/td&gt;</span><br><span class="line">                    &lt;td&gt;&lt;%=book.getBookImgPath() %&gt;&lt;/td&gt;</span><br><span class="line">                    &lt;td&gt;&lt;%=book.getBookDesc() %&gt;&lt;/td&gt;</span><br><span class="line">                    &lt;td&gt;&lt;%=book.getBookType() %&gt;&lt;/td&gt;</span><br><span class="line">                &lt;/tr&gt;</span><br><span class="line">            &lt;%</span><br><span class="line">            &#125;</span><br><span class="line">            %&gt;</span><br><span class="line">        &lt;/table&gt;</span><br><span class="line"></span><br><span class="line">    &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<h2 id="三、JSP开发详解"><a href="#三、JSP开发详解" class="headerlink" title="三、JSP开发详解"></a>三、JSP开发详解</h2><h3 id="3-1-JSP和Servlet"><a href="#3-1-JSP和Servlet" class="headerlink" title="3.1 JSP和Servlet"></a>3.1 JSP和Servlet</h3><blockquote>
<p>JSP和Servlet一样可以接受客户端请求，并响应一个动态网页。</p>
</blockquote>
<p>JSP是对Servlet的一种高级封装，<strong>一个JSP文件底层就是一个Servlet类</strong>。</p>
<p>JSP文件需要依赖服务器运行，当客户端请求一个JSP文件时，JSP文件会在服务器中转换成Servlet来执行。</p>
<p><img src="/imgs/image-20211115143508765.png" class="lazyload" data-srcset="/imgs/image-20211115143508765.png" srcset="" alt="image-20211115143508765"></p>
<p>使用JSP的必要性：</p>
<p>​	我们将动态网页显示使用JSP完成，在HTML标签中嵌入Java代码的形式开发动态网页更为便捷。</p>
<h3 id="3-2-JSP开发的语法规则"><a href="#3-2-JSP开发的语法规则" class="headerlink" title="3.2 JSP开发的语法规则"></a>3.2 JSP开发的语法规则</h3><h4 id="3-2-1-JSP文档规范"><a href="#3-2-1-JSP文档规范" class="headerlink" title="3.2.1 JSP文档规范"></a>3.2.1 JSP文档规范</h4><ul>
<li><p>JSP文件和HTML文档一样是一个视图文件，JSP文件创建在项目的web目录</p>
</li>
<li><p>JSP文件以<code>.jsp</code>后缀名结尾</p>
</li>
<li><p>JSP文档内容结构：</p>
<ul>
<li><p>在JSP文件的第一行需要通过 <code>&lt;%@ page %&gt;</code>声明使用java语言</p>
</li>
<li><p>JSP文件的主体内容是一个HTML文档，符合HTML的文档规范</p>
</li>
</ul>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">    &lt;head&gt;</span><br><span class="line">        &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">    &lt;/head&gt;</span><br><span class="line">    &lt;body&gt;</span><br><span class="line">        </span><br><span class="line">    &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="3-2-2-Java脚本"><a href="#3-2-2-Java脚本" class="headerlink" title="3.2.2 Java脚本"></a>3.2.2 Java脚本</h4><blockquote>
<p>JSP页面可以嵌入java代码，java代码就是这个页面的脚本</p>
</blockquote>
<ul>
<li><p>java代码：在jsp中的java代码必须写在<code>&lt;%  %&gt;</code>中，代码可以写在JSP文件的任何位置，而且可以包含多段代码</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;%</span><br><span class="line">   java代码</span><br><span class="line">%&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>变量输出</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;img src=<span class="string">&quot;&lt;%=attr %&gt;&quot;</span>/&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>声明成员变量和方法：</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;%! <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">5</span>;%&gt;</span><br><span class="line"></span><br><span class="line">&lt;%! </span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">method</span><span class="params">()</span>&#123;</span><br><span class="line">     System.out.println(<span class="string">&quot;hello&quot;</span>);  </span><br><span class="line">  &#125;  </span><br><span class="line">%&gt;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="3-2-3-JSP注释"><a href="#3-2-3-JSP注释" class="headerlink" title="3.2.3 JSP注释"></a>3.2.3 JSP注释</h4><ul>
<li><p>HTML文档注释</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- HTML文档注释：这种注释会出现在jsp编译之后的Java代码中 --&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>JSP注释</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;%-- JSP 注释： 这种注释不会出现在编译后的java代码  --%&gt;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="3-3-JSP编译指令"><a href="#3-3-JSP编译指令" class="headerlink" title="3.3 JSP编译指令"></a>3.3 JSP编译指令</h3><p>编译指令：在JSP文件转换成Java代码之后，编译成.class文件的过程中执行的指令</p>
<blockquote>
<p>&lt;%@ page %&gt; : 声明当前JSP页面在web容器中的配置、引用；</p>
<p>&lt;%@ include %&gt; : 在当前JSP中引用其他的资源（JSP\HTML）作为当前JSP的一部分；</p>
<p>&lt;%@ taglib %&gt; : 引用第三方标签库、扩展JSP文件中的标签；</p>
</blockquote>
<h4 id="3-3-1"><a href="#3-3-1" class="headerlink" title="3.3.1 &lt;%@ page%&gt;"></a>3.3.1 &lt;%@ page%&gt;</h4><table>
<thead>
<tr>
<th>标签属性</th>
<th>说明</th>
<th>示例</th>
</tr>
</thead>
<tbody><tr>
<td>contentType</td>
<td>用于声明当前JSP文档的MIME类型和字符集编码</td>
<td>contentType&#x3D;”text&#x2F;html;charset&#x3D;UTF-8”</td>
</tr>
<tr>
<td>language</td>
<td>定义JSP中所用的脚本语言类型，默认java</td>
<td>language&#x3D;”java”</td>
</tr>
<tr>
<td>import</td>
<td>声明当前JSP中的Java代码依赖的类</td>
<td>import&#x3D;”java.util.List”</td>
</tr>
<tr>
<td>pageEncoding</td>
<td>声明当前JSP文档的解码格式</td>
<td>pageEncoding&#x3D;”UTF-8”</td>
</tr>
<tr>
<td>errorPage</td>
<td>如果当前JSP出现异常则跳转到errorPage指向页面</td>
<td>errorPage&#x3D;”error.jsp”</td>
</tr>
<tr>
<td>isErrorPage</td>
<td>定义当前页面是否可以作为错误页面</td>
<td>isErrorPage&#x3D;”true”</td>
</tr>
</tbody></table>
<h4 id="3-3-2"><a href="#3-3-2" class="headerlink" title="3.3.2 &lt;%@ include %&gt;"></a>3.3.2 &lt;%@ include %&gt;</h4><blockquote>
<p>在当前JSP中引用其他的资源（JSP\HTML）作为当前JSP的一部分，被引入的页面不会单独作为一个JSP编译，而是将引入的页面中的代码插入到当前JSP之后作为一个整体进行编译。</p>
<p>被引入的页面只需要是一个HTML片段即可。</p>
<p><code>静态引入</code>：将被页面引入到当前JSP之后再进行整体的编译，被引入的页面不会单独编译。</p>
</blockquote>
<ul>
<li><p>header.jsp</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;div style=<span class="string">&quot;height: 100px; background: deepskyblue&quot;</span> &gt;header&lt;/div&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>footer.jsp</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;div style=<span class="string">&quot;height: 50px; background: lightgray&quot;</span> &gt;footer&lt;/div&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>index.jsp</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;%@ page <span class="keyword">import</span>=<span class="string">&quot;java.util.Date&quot;</span>%&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;title&gt;$Title$&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">   </span><br><span class="line">    &lt;%@ include file=<span class="string">&quot;header.jsp&quot;</span>%&gt;</span><br><span class="line">    &lt;div style=<span class="string">&quot;height: 400px; background: orange&quot;</span>&gt;index&lt;/div&gt;</span><br><span class="line">    &lt;%@ include file=<span class="string">&quot;footer.jsp&quot;</span>%&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="3-3-3"><a href="#3-3-3" class="headerlink" title="3.3.3 &lt;%@ taglib %&gt;"></a>3.3.3 &lt;%@ taglib %&gt;</h4><blockquote>
<p>引用第三方标签库、扩展JSP文件中的标签</p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--引入JSTL标签库--&gt;</span><br><span class="line">&lt;%@ taglib prefix=<span class="string">&quot;c&quot;</span> uri=<span class="string">&quot;http://java.sun.com/jsp/jstl/core&quot;</span> %&gt;</span><br></pre></td></tr></table></figure>

<h3 id="3-4-JSP动作指令"><a href="#3-4-JSP动作指令" class="headerlink" title="3.4 JSP动作指令"></a>3.4 JSP动作指令</h3><blockquote>
<p>在JSP文件中，除了支持标准的HTML标签库和编译指令之外，还支持JSP特有的动作指令（动作标签）。</p>
<p>动作指令：在JSP中以<code>jsp:</code>开头的、在JSP页面运行期间执行的指令。</p>
</blockquote>
<h4 id="3-4-1-jsp-include"><a href="#3-4-1-jsp-include" class="headerlink" title="3.4.1 jsp:include"></a>3.4.1 jsp:include</h4><figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;%-- 动态引入 --%&gt;</span><br><span class="line">&lt;jsp:include page=<span class="string">&quot;test1.jsp&quot;</span>/&gt;</span><br></pre></td></tr></table></figure>

<p>动态引入JSP文件文件：被引入的JSP文件先单独编译执行，将执行的结果引入到当前JSP文件。</p>
<p>因为被引入的JSP页面需要独立的编译执行，因此被引入的页面需要是一个完整的JSP文件。</p>
<p>在动态引入的页面中不能访问主页面中定义的Java变量。</p>
<p><strong>静态引入和动态引入的区别：</strong></p>
<ul>
<li>静态引入，使用<code>&lt;%@include file=&quot;&quot;%&gt;</code>编译指令将HTML或者JSP页面引入到当前文件，静态引入是先引入再执行，因此被引入的页面可以是一个HTML片段，也可在被引入的页面中访问主页面定义的Java变量；</li>
<li>动态引入，使用<code>&lt;jsp:include page=&quot;&quot;/&gt;</code>动作指令将JSP页面引入到当前文件，动态引入是先独立编译执行被引入的页面，将执行结果引入到当前页面，被引入的页面需要独立执行因此必须是一个完成的JSP，同时在被引入的JSP中不能访问主页面定义的Java变量。</li>
</ul>
<h4 id="3-4-2-jsp-userBean"><a href="#3-4-2-jsp-userBean" class="headerlink" title="3.4.2 jsp:userBean"></a>3.4.2 jsp:userBean</h4><blockquote>
<p>在JSP页面中构造Java对象</p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;%-- 相当于 <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Book</span>(); --%&gt;</span><br><span class="line">&lt;jsp:useBean id=<span class="string">&quot;book&quot;</span> class=<span class="string">&quot;com.qfedu.jsp.dto.Book&quot;</span>&gt;&lt;/jsp:useBean&gt;</span><br></pre></td></tr></table></figure>

<ul>
<li>id属性， 创建的对象的变量名</li>
<li>class属性，类的全限定名</li>
</ul>
<h4 id="3-4-3-jsp-setProperty"><a href="#3-4-3-jsp-setProperty" class="headerlink" title="3.4.3 jsp:setProperty"></a>3.4.3 jsp:setProperty</h4><blockquote>
<p>给创建的Java对象属性赋值</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;%-- 相当于 book.setBookId(<span class="string">&quot;100001&quot;</span>)   --%&gt;</span><br><span class="line">&lt;jsp:setProperty name=<span class="string">&quot;book&quot;</span> property=<span class="string">&quot;bookId&quot;</span> value=<span class="string">&quot;100001&quot;</span>&gt;&lt;/jsp:setProperty&gt;</span><br><span class="line">&lt;jsp:setProperty name=<span class="string">&quot;book&quot;</span> property=<span class="string">&quot;bookName&quot;</span> value=<span class="string">&quot;Java&quot;</span>&gt;&lt;/jsp:setProperty&gt;</span><br></pre></td></tr></table></figure>

<ul>
<li>name属性，对象的变量名</li>
<li>property属性，对象的属性名</li>
<li>values属性，属性的值</li>
</ul>
<h4 id="3-4-4-jsp-getProperty"><a href="#3-4-4-jsp-getProperty" class="headerlink" title="3.4.4 jsp:getProperty"></a>3.4.4 jsp:getProperty</h4><blockquote>
<p>获取创建的对象的值，并输出到网页</p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;%-- 相当于 book.getBookId()，并将获取的值输出到页面   --%&gt;</span><br><span class="line">&lt;jsp:getProperty name=<span class="string">&quot;book&quot;</span> property=<span class="string">&quot;bookId&quot;</span>/&gt;</span><br></pre></td></tr></table></figure>

<ul>
<li>name属性，对象的变量名</li>
<li>property属性，对象的属性名</li>
</ul>
<h4 id="3-4-5-jsp-forward"><a href="#3-4-5-jsp-forward" class="headerlink" title="3.4.5 jsp:forward"></a>3.4.5 jsp:forward</h4><blockquote>
<p>用于转发客户端请求</p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;jsp:forward page=<span class="string">&quot;test2.jsp&quot;</span>&gt;&lt;/jsp:forward&gt;</span><br></pre></td></tr></table></figure>

<h4 id="3-4-6-jsp-param"><a href="#3-4-6-jsp-param" class="headerlink" title="3.4.6 jsp:param"></a>3.4.6 jsp:param</h4><blockquote>
<p>在JSP页面转发过程中进行参数传递</p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;%--  从当前JSP转发到另一个JSP   --%&gt;</span><br><span class="line">&lt;jsp:forward page=<span class="string">&quot;test2.jsp&quot;</span>&gt;</span><br><span class="line">    &lt;%-- 转发的同时携带参数  --%&gt;</span><br><span class="line">    &lt;jsp:param name=<span class="string">&quot;name&quot;</span> value=<span class="string">&quot;zhangsan&quot;</span>/&gt;</span><br><span class="line">    &lt;jsp:param name=<span class="string">&quot;sex&quot;</span> value=<span class="string">&quot;nan&quot;</span>/&gt;</span><br><span class="line">&lt;/jsp:forward&gt;</span><br></pre></td></tr></table></figure>

<h3 id="3-5-JSP九大内置对象"><a href="#3-5-JSP九大内置对象" class="headerlink" title="3.5 JSP九大内置对象"></a>3.5 JSP九大内置对象</h3><blockquote>
<p>一个JSP文件在服务器上是转换成Java文件（Servlet类）编译执行的，我们在JSP文件中嵌入的Java代码都会转换到这个Java文件的方法中（_jspService）,因此这个方法的参数、方法中定义的变量以及当前类继承的父类中定义的变量，我们的代码都可以使用。</p>
<p>在JSP中编写Java代码可以不用创建、直接使用的对象我们称之为JSP内置对象。</p>
</blockquote>
<table>
<thead>
<tr>
<th>对象名</th>
<th>类型</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td><code>request</code></td>
<td>javax.servlet.http.HttpServletRequest</td>
<td>表示客户端请求对象，用户获取HTTP请求信息</td>
</tr>
<tr>
<td>response</td>
<td>javax.servlet.http.HttpServletResponse</td>
<td>表示服务器对客户端的响应对象，用于将JSP处理的数据响应给客户端</td>
</tr>
<tr>
<td><code>session</code></td>
<td>javax.servlet.http.HttpSession</td>
<td>表示当前客户端与服务器的会话对象</td>
</tr>
<tr>
<td><code>application</code></td>
<td>javax.servlet.ServletContext</td>
<td>当前web应用在服务器上的全局对象</td>
</tr>
<tr>
<td>config</td>
<td>javax.servlet.ServletConfig</td>
<td>表示当前Servlet类的配置信息</td>
</tr>
<tr>
<td><code>pageContext</code></td>
<td>javax.servlet.jsp.PageContext</td>
<td>当前JSP的上下文，可以获取当前JSP的任何信息</td>
</tr>
<tr>
<td>out</td>
<td>javax.servlet.jsp.JspWriter</td>
<td>指向当前JSP文档的输出流</td>
</tr>
<tr>
<td>exception</td>
<td>java.lang.Throwable</td>
<td>只有在设置了isErrorPage&#x3D;“true”的JSP可使用</td>
</tr>
<tr>
<td>page</td>
<td>java.lang.Object</td>
<td>当前JSP转换的servlet类的实例，相当于this</td>
</tr>
</tbody></table>
<h3 id="3-6-JSP四大域对象"><a href="#3-6-JSP四大域对象" class="headerlink" title="3.6 JSP四大域对象"></a>3.6 JSP四大域对象</h3><blockquote>
<p>域对象——可以用来存取数据的对象</p>
<ul>
<li>pageContext</li>
<li>request</li>
<li>session</li>
<li>application</li>
</ul>
</blockquote>
<h4 id="3-6-1-pageContext"><a href="#3-6-1-pageContext" class="headerlink" title="3.6.1 pageContext"></a>3.6.1 pageContext</h4><blockquote>
<p>pageConext对象 只作用于当前JSP文件</p>
</blockquote>
<p><img src="/imgs/image-20211115192340756.png" class="lazyload" data-srcset="/imgs/image-20211115192340756.png" srcset="" alt="image-20211115192340756"></p>
<h4 id="3-6-2-request"><a href="#3-6-2-request" class="headerlink" title="3.6.2 request"></a>3.6.2 request</h4><blockquote>
<p>request作用于一次请求</p>
</blockquote>
<p><img src="/imgs/image-20211115193904951.png" class="lazyload" data-srcset="/imgs/image-20211115193904951.png" srcset="" alt="image-20211115193904951"></p>
<h4 id="3-6-3-session"><a href="#3-6-3-session" class="headerlink" title="3.6.3 session"></a>3.6.3 session</h4><blockquote>
<p>session对象作用于用户一次连接的多次请求</p>
</blockquote>
<p><img src="/imgs/image-20211115193438233.png" class="lazyload" data-srcset="/imgs/image-20211115193438233.png" srcset="" alt="image-20211115193438233"></p>
<h4 id="3-6-4-application"><a href="#3-6-4-application" class="headerlink" title="3.6.4 application"></a>3.6.4 application</h4><blockquote>
<p>application实际上就是servletContext对象，作用于一个web应用的所有用户</p>
</blockquote>
<p><img src="/imgs/image-20211115193814764.png" class="lazyload" data-srcset="/imgs/image-20211115193814764.png" srcset="" alt="image-20211115193814764"></p>
<h4 id="3-6-5-使用域对象传值示例"><a href="#3-6-5-使用域对象传值示例" class="headerlink" title="3.6.5 使用域对象传值示例"></a>3.6.5 使用域对象传值示例</h4><ul>
<li><p>Servlet类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.jsp.servlets;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@WebServlet(&quot;/TestServlet&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestServlet</span> <span class="keyword">extends</span> <span class="title class_">HttpServlet</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doGet</span><span class="params">(HttpServletRequest req, HttpServletResponse resp)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        doPost(req, resp);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doPost</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//1.分别通过 request、session、application传值</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;key1&quot;</span>,<span class="string">&quot;value1&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">HttpSession</span> <span class="variable">session</span> <span class="operator">=</span> request.getSession();</span><br><span class="line">        session.setAttribute(<span class="string">&quot;key2&quot;</span>,<span class="string">&quot;value2&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">ServletContext</span> <span class="variable">application</span> <span class="operator">=</span> getServletContext();</span><br><span class="line">        application.setAttribute(<span class="string">&quot;key3&quot;</span>,<span class="string">&quot;value3&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.转发到test3.jsp</span></span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;test3.jsp&quot;</span>).forward(request,response);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>JSP页面</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">Test3</span><br><span class="line">&lt;hr/&gt;</span><br><span class="line"></span><br><span class="line">&lt;%</span><br><span class="line">    <span class="type">String</span> <span class="variable">s1</span> <span class="operator">=</span> (String) request.getAttribute(<span class="string">&quot;key1&quot;</span>);</span><br><span class="line">    <span class="type">String</span> <span class="variable">s2</span> <span class="operator">=</span> (String) session.getAttribute(<span class="string">&quot;key2&quot;</span>);</span><br><span class="line">    <span class="type">String</span> <span class="variable">s3</span> <span class="operator">=</span> (String) application.getAttribute(<span class="string">&quot;key3&quot;</span>);</span><br><span class="line">%&gt;</span><br><span class="line">request取出的数据:&lt;%=s1%&gt; &lt;br/&gt;</span><br><span class="line">session取出的数据:&lt;%=s2%&gt; &lt;br/&gt;</span><br><span class="line">application取出的数据:&lt;%=s3%&gt; &lt;br/&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="3-7-JSP开发应用"><a href="#3-7-JSP开发应用" class="headerlink" title="3.7 JSP开发应用"></a>3.7 JSP开发应用</h3><p><img src="/imgs/image-20211115210009119.png" class="lazyload" data-srcset="/imgs/image-20211115210009119.png" srcset="" alt="image-20211115210009119"></p>
<ul>
<li>JSP负责项目中的视图呈现</li>
<li>Servlet负责接收、处理用户请求</li>
<li>Servlet类查询的数据转发并传递给JSP页面进行显示</li>
</ul>
<p><code>注意：当将进行页面显示的Servlet类转换成jsp文件之后，要修改对应跳转的路径；同时注意修改登录过滤器的放行路径，以及未登录时要跳转到login.jsp（而不是原来的LoginPageServlet）</code></p>
<h2 id="四、EL表达式"><a href="#四、EL表达式" class="headerlink" title="四、EL表达式"></a>四、EL表达式</h2><blockquote>
<p>思考问题：JSP相较于Servlet来说，在动态网页的数据渲染方面要便捷很多，但是依然要进行HTML和Java代码的混合编程，代码的可读性和维护性依然有待提高，能不能做HTML和Java代码的完全分离呢？</p>
</blockquote>
<h3 id="4-1-什么是EL"><a href="#4-1-什么是EL" class="headerlink" title="4.1 什么是EL?"></a>4.1 什么是EL?</h3><blockquote>
<p>Expression Language 表达式语言，应用于JSP页面，可以更简单、便捷的获取page、request、session、application等作用域的值，进行渲染。</p>
</blockquote>
<p><strong>EL表达式就是替代以下代码的作用</strong>：</p>
<ul>
<li>pageContext.getAttribute(“key”);</li>
<li>request.getAttribute(“key”);</li>
<li>session.getAttribute(“key”);</li>
<li>application.getAttribute(“key”);</li>
</ul>
<p><strong>EL表达式使用示例：</strong></p>
<ul>
<li><p>Servlet类:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@WebServlet(&quot;/TestServlet&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestServlet</span> <span class="keyword">extends</span> <span class="title class_">HttpServlet</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doGet</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span></span><br><span class="line">            <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        doPost(request, response);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doPost</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span></span><br><span class="line">            <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        <span class="comment">//1.传递数据</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;str&quot;</span>,<span class="string">&quot;Hello EL!&quot;</span>);</span><br><span class="line">        <span class="comment">//2.转发到JSP页面</span></span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;test.jsp&quot;</span>).forward(request,response);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>JSP文件：</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">    &lt;head&gt;</span><br><span class="line">        &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">    &lt;/head&gt;</span><br><span class="line">    &lt;body&gt;</span><br><span class="line">        &lt;%-- 使用Java代码接收数据 --%&gt;</span><br><span class="line">        &lt;%</span><br><span class="line">            <span class="type">String</span> <span class="variable">s</span> <span class="operator">=</span> (String) request.getAttribute(<span class="string">&quot;str&quot;</span>);</span><br><span class="line">        %&gt;</span><br><span class="line">        Java脚本获取的数据：&lt;%=s %&gt;</span><br><span class="line"></span><br><span class="line">        &lt;%--  通过EL获取并显示TestServlet传递的数据  --%&gt;</span><br><span class="line">        EL表达式获取的数据：$&#123;str&#125;</span><br><span class="line">    &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="4-2-EL表达式应用"><a href="#4-2-EL表达式应用" class="headerlink" title="4.2 EL表达式应用"></a>4.2 EL表达式应用</h3><h4 id="4-2-1-实体类"><a href="#4-2-1-实体类" class="headerlink" title="4.2.1 实体类"></a>4.2.1 实体类</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.dto;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 图书信息实体类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Book</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String bookId;</span><br><span class="line">    <span class="keyword">private</span> String bookName;</span><br><span class="line">    <span class="keyword">private</span> String bookAuthor;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">double</span> bookPrice;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//无参构造器</span></span><br><span class="line">    <span class="comment">//全参构造器</span></span><br><span class="line">    <span class="comment">//toString</span></span><br><span class="line">    <span class="comment">//get和set方法</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="4-2-2-TestServlet类"><a href="#4-2-2-TestServlet类" class="headerlink" title="4.2.2 TestServlet类"></a>4.2.2 TestServlet类</h4><ul>
<li>在TestServlet类传递各种数据，并转发到test.jsp页面</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.servlets;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.qfedu.dto.Book;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.ServletException;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.annotation.WebServlet;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServlet;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@WebServlet(&quot;/TestServlet&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TestServlet</span> <span class="keyword">extends</span> <span class="title class_">HttpServlet</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doGet</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span></span><br><span class="line">            <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        doPost(request, response);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doPost</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span></span><br><span class="line">            <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        <span class="comment">//1.传递数据</span></span><br><span class="line">        <span class="comment">//简单类型</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;key1&quot;</span>,<span class="number">123</span>);</span><br><span class="line">        <span class="comment">//字符串</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;key2&quot;</span>,<span class="string">&quot;Hello EL!&quot;</span>);</span><br><span class="line">        <span class="comment">//对象</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;key3&quot;</span>,<span class="keyword">new</span> <span class="title class_">Book</span>(<span class="string">&quot;1001&quot;</span>,<span class="string">&quot;Java&quot;</span>,<span class="string">&quot;亮亮&quot;</span>,<span class="number">20.00</span>));</span><br><span class="line">        <span class="comment">//数组</span></span><br><span class="line">        String[] arr = &#123;<span class="string">&quot;aaa&quot;</span>,<span class="string">&quot;bbb&quot;</span>,<span class="string">&quot;ccc&quot;</span>&#125;;</span><br><span class="line">        request.setAttribute(<span class="string">&quot;key4&quot;</span>,arr);</span><br><span class="line">        <span class="comment">//集合</span></span><br><span class="line">        List&lt;Book&gt; bookList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        bookList.add(<span class="keyword">new</span> <span class="title class_">Book</span>(<span class="string">&quot;1001&quot;</span>,<span class="string">&quot;Java&quot;</span>,<span class="string">&quot;亮亮&quot;</span>,<span class="number">20.00</span>));</span><br><span class="line">        bookList.add(<span class="keyword">new</span> <span class="title class_">Book</span>(<span class="string">&quot;1002&quot;</span>,<span class="string">&quot;C++&quot;</span>,<span class="string">&quot;张三&quot;</span>,<span class="number">21.00</span>));</span><br><span class="line">        bookList.add(<span class="keyword">new</span> <span class="title class_">Book</span>(<span class="string">&quot;1003&quot;</span>,<span class="string">&quot;Python&quot;</span>,<span class="string">&quot;李四&quot;</span>,<span class="number">22.00</span>));</span><br><span class="line">        request.setAttribute(<span class="string">&quot;key5&quot;</span>,bookList);</span><br><span class="line">        <span class="comment">//Map</span></span><br><span class="line">        Map&lt;String,Book&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line">        map.put(<span class="string">&quot;a1001&quot;</span>,<span class="keyword">new</span> <span class="title class_">Book</span>(<span class="string">&quot;1001&quot;</span>,<span class="string">&quot;Java&quot;</span>,<span class="string">&quot;亮亮&quot;</span>,<span class="number">20.00</span>));</span><br><span class="line">        map.put(<span class="string">&quot;a1002&quot;</span>,<span class="keyword">new</span> <span class="title class_">Book</span>(<span class="string">&quot;1002&quot;</span>,<span class="string">&quot;C++&quot;</span>,<span class="string">&quot;张三&quot;</span>,<span class="number">21.00</span>));</span><br><span class="line">        map.put(<span class="string">&quot;a1003&quot;</span>,<span class="keyword">new</span> <span class="title class_">Book</span>(<span class="string">&quot;1003&quot;</span>,<span class="string">&quot;Python&quot;</span>,<span class="string">&quot;李四&quot;</span>,<span class="number">22.00</span>));</span><br><span class="line">        request.setAttribute(<span class="string">&quot;key6&quot;</span>,map);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.转发到JSP页面</span></span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;test.jsp&quot;</span>).forward(request,response);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="4-2-3-test-jsp"><a href="#4-2-3-test-jsp" class="headerlink" title="4.2.3 test.jsp"></a>4.2.3 test.jsp</h4><ul>
<li>在test.jsp页面通过EL表达式获取各种类型数据</li>
</ul>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">    &lt;head&gt;</span><br><span class="line">        &lt;title&gt;Title&lt;/title&gt;</span><br><span class="line">    &lt;/head&gt;</span><br><span class="line">    &lt;body&gt;</span><br><span class="line">&lt;%--  <span class="number">1.</span>接收简单类型及字符串 $&#123;key&#125;  --%&gt;</span><br><span class="line">    $&#123;key1&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key2&#125;&lt;br/&gt;</span><br><span class="line"></span><br><span class="line">&lt;%--  <span class="number">2.</span>接收对象数据  $&#123;key&#125;获取对象的toString方法输出，</span><br><span class="line">      我们可以通过 $&#123;key.attrName&#125;获取对象属性值，通过反射调用类中属性的get方法获取属性值</span><br><span class="line">       因此传递到JSP页面、使用EL表达式获取属性值的对象必须提供get方法 --%&gt;</span><br><span class="line">    $&#123;key3&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key3.bookId&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key3.bookName&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key3.bookAuthor&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key3.bookPrice&#125;&lt;br/&gt;</span><br><span class="line"></span><br><span class="line">&lt;%-- <span class="number">3.</span>接收数组数据  $&#123;key[index]&#125; --%&gt;</span><br><span class="line">    $&#123;key4[<span class="number">0</span>]&#125;-$&#123;key4[<span class="number">1</span>]&#125;-$&#123;key4[<span class="number">2</span>]&#125;&lt;br/&gt;</span><br><span class="line"></span><br><span class="line">&lt;%-- <span class="number">4.</span>接收集合中的数据：$&#123;key[index]&#125;</span><br><span class="line">     如何集合中的元素是对象 ，可以进一步使用 $&#123;key[index].attrName&#125; 获取集合中对象的属性--%&gt;</span><br><span class="line">    $&#123;key5[<span class="number">0</span>].bookName&#125;- $&#123;key5[<span class="number">0</span>].bookAuthor&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key5[<span class="number">1</span>].bookName&#125;- $&#123;key5[<span class="number">1</span>].bookAuthor&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key5[<span class="number">2</span>].bookName&#125;- $&#123;key5[<span class="number">2</span>].bookAuthor&#125;&lt;br/&gt;</span><br><span class="line"></span><br><span class="line">&lt;%-- <span class="number">5.</span>接收Map中的数据: 使用$&#123;key&#125;获取整个map</span><br><span class="line">                    使用$&#123;key.mapKey&#125; 根据可以获取元素</span><br><span class="line">                    如果map中的key是以数字开头，可以使用$&#123;key[<span class="string">&#x27;mapKey&#x27;</span>]&#125;</span><br><span class="line">     如果map中的value是对象，我们还可以进一步使用 $&#123;key.mapKey.attrName&#125;获取对象属性值--%&gt;</span><br><span class="line">    $&#123;key6[<span class="string">&#x27;a1001&#x27;</span>]&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key6.a1001&#125;&lt;br/&gt;</span><br><span class="line">    $&#123;key6.a1001.bookName&#125;&lt;br/&gt;</span><br><span class="line"></span><br><span class="line">    &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<h3 id="4-3-EL访问域对象"><a href="#4-3-EL访问域对象" class="headerlink" title="4.3 EL访问域对象"></a>4.3 EL访问域对象</h3><blockquote>
<p>如果从Servlet分别使用request、session、application同时向JSP页面传递数据，并且key都相同；那么在JSP页面直接使用${key}获取的是什么数据呢？ 如何能够获取我们想要访问的域对象中的数据呢？</p>
</blockquote>
<p><img src="/imgs/image-20211116003956162.png" class="lazyload" data-srcset="/imgs/image-20211116003956162.png" srcset="" alt="image-20211116003956162"></p>
<h4 id="4-3-1-key-获取哪个域对象的数据呢？"><a href="#4-3-1-key-获取哪个域对象的数据呢？" class="headerlink" title="4.3.1 ${key}获取哪个域对象的数据呢？"></a>4.3.1 ${key}获取哪个域对象的数据呢？</h4><ul>
<li>四个域对象的访问从小到大依次是：pageContext–&gt;request–&gt;session–&gt;application</li>
<li>如果没有指定域对象，${key}默认获取最小域对象中的数据</li>
</ul>
<h4 id="4-3-2-如何使用EL获取指定域对象数据？"><a href="#4-3-2-如何使用EL获取指定域对象数据？" class="headerlink" title="4.3.2 如何使用EL获取指定域对象数据？"></a>4.3.2 如何使用EL获取指定域对象数据？</h4><ul>
<li><p>在EL表达式中，分别为四个域对象各自取了一个名字</p>
<ul>
<li>pageContext对象 —&gt; pageScope</li>
<li>request对象—&gt;requestScope</li>
<li>session对象—&gt;sessionScope</li>
<li>application对象—&gt;applicationScope</li>
</ul>
</li>
<li><p>在JSP中如果多个域对象都有相同的key，可以通过<code>$&#123;***Scope.key&#125;</code>来获取指定域对象中数据，如果获取不到则返回””，显示到页面为空白</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$&#123;sessionScope.key&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="4-4-EL的隐式对象"><a href="#4-4-EL的隐式对象" class="headerlink" title="4.4 EL的隐式对象"></a>4.4 EL的隐式对象</h3><blockquote>
<p>EL语法中提供的隐藏对象——隐式对象</p>
<p>除了四个域对象pageScope、requestScope、sessionScope、applicationScope之外，EL中还提供了另外七个隐式对象，分别用于获取不同的数据</p>
</blockquote>
<table>
<thead>
<tr>
<th>隐式对象</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>param</td>
<td>获取Rquest对象的参数，返回String，<br/><code>$&#123;param.key&#125;</code>等价于<code>request.getParameter(&quot;key&quot;)</code></td>
</tr>
<tr>
<td>paramValues</td>
<td>获取Rquest对象传递的所有的参数值，返回字符串集合<br> <code>$&#123;paramValues&#125;</code>等价于<code>request.getParameterValues()</code></td>
</tr>
<tr>
<td>header</td>
<td>获取HTTP请求头  <code>$&#123;header.contentPosition&#125;</code></td>
</tr>
<tr>
<td>headerValues</td>
<td>获取HTTP请求头中所有的值</td>
</tr>
<tr>
<td>initParam</td>
<td>获取上下文初始化参数</td>
</tr>
<tr>
<td>pageContext</td>
<td>获取当前页面的pageContext对象：  <br><code>$&#123;pageContext.request.contextPath&#125;</code>当前web项目在服务器的访问路径</td>
</tr>
<tr>
<td>cookie</td>
<td>获取cookie中的值，${cookie.username}</td>
</tr>
</tbody></table>
<h3 id="4-5-EL的运算符"><a href="#4-5-EL的运算符" class="headerlink" title="4.5 EL的运算符"></a>4.5 EL的运算符</h3><p>EL表达式不能能够从域对象获取数据，同时可以对取出的数据进行算术运算、关系比较、逻辑运算等运算</p>
<h4 id="4-5-1-算术运算"><a href="#4-5-1-算术运算" class="headerlink" title="4.5.1 算术运算"></a>4.5.1 算术运算</h4><table>
<thead>
<tr>
<th>运算符</th>
<th>描述&#x2F;示例</th>
</tr>
</thead>
<tbody><tr>
<td>+</td>
<td><code>$&#123;key1+key2&#125;</code>  表示根据key1获取的值然后加上key2获取的值，显示到网页</td>
</tr>
<tr>
<td>-</td>
<td>减法</td>
</tr>
<tr>
<td>*</td>
<td>乘法</td>
</tr>
<tr>
<td>&#x2F;  or  div</td>
<td>除法，   <code>$&#123;key/4&#125;</code> 等价于 <code>$&#123;key div 4&#125;</code></td>
</tr>
<tr>
<td>% or mod</td>
<td>取模</td>
</tr>
</tbody></table>
<h4 id="4-5-2-关系比较"><a href="#4-5-2-关系比较" class="headerlink" title="4.5.2 关系比较"></a>4.5.2 关系比较</h4><table>
<thead>
<tr>
<th>运算符</th>
<th>描述&#x2F;示例</th>
</tr>
</thead>
<tbody><tr>
<td><code>==</code> or <code>eq</code></td>
<td><code>$&#123;key == v&#125;</code>  表示比较根据key获取的值是否等于v，返回结果为true&#x2F;false<br>等价于 <code>$&#123;key eq v&#125;</code></td>
</tr>
<tr>
<td><code>!=</code> or <code>ne</code></td>
<td>不等于</td>
</tr>
<tr>
<td><code>&gt;</code> or  <code>gt</code></td>
<td>大于</td>
</tr>
<tr>
<td><code>&lt; </code> or <code>lt</code></td>
<td>小于</td>
</tr>
<tr>
<td><code>&gt;=</code> or <code>ge</code></td>
<td>大于等于</td>
</tr>
<tr>
<td><code>&lt;=</code> or <code>le</code></td>
<td>小于等于</td>
</tr>
</tbody></table>
<h4 id="4-5-3-逻辑运算"><a href="#4-5-3-逻辑运算" class="headerlink" title="4.5.3 逻辑运算"></a>4.5.3 逻辑运算</h4><table>
<thead>
<tr>
<th>运算符</th>
<th>描述&#x2F;示例</th>
</tr>
</thead>
<tbody><tr>
<td><code>&amp;&amp;</code> or <code>and</code></td>
<td>逻辑与,用于连接两个条件</td>
</tr>
<tr>
<td>&#96;</td>
<td></td>
</tr>
<tr>
<td><code>!</code> or <code>not</code></td>
<td>逻辑非</td>
</tr>
</tbody></table>
<h4 id="4-5-4-判空"><a href="#4-5-4-判空" class="headerlink" title="4.5.4 判空"></a>4.5.4 判空</h4><table>
<thead>
<tr>
<th>运算符</th>
<th>描述&#x2F;示例</th>
</tr>
</thead>
<tbody><tr>
<td>empty</td>
<td><code>$&#123;empty key&#125;</code> 如果key对应取出的值为空，则返回true</td>
</tr>
</tbody></table>
<h2 id="五、JSTL"><a href="#五、JSTL" class="headerlink" title="五、JSTL"></a>五、JSTL</h2><blockquote>
<p>如果EL表达式在JSP页面中获取的集合中的元素个数不确定，我们该如何将集合中的数据全部显示呢？</p>
</blockquote>
<h3 id="5-1-JSTL简介"><a href="#5-1-JSTL简介" class="headerlink" title="5.1 JSTL简介"></a>5.1 JSTL简介</h3><blockquote>
<p>JSTL (JSP Standard Tag Library) JSP标准标签库，用于扩展JSP中的标签，能够为JSP页面提供流程控制、类型转换等功能的标签。</p>
<p>作用：在JSP中通常是JSTL+EL的组合来进行数据的提取及渲染。</p>
</blockquote>
<p>JSTL标签库提供了多类标签：</p>
<ul>
<li>c ，核心标签库，提供流程控制的标签</li>
<li>fmt，转换标签库，提供了日期、数值类型转换的标签</li>
<li>sql</li>
<li>fn</li>
<li>x</li>
</ul>
<h3 id="5-2-JSTL的引入步骤"><a href="#5-2-JSTL的引入步骤" class="headerlink" title="5.2 JSTL的引入步骤"></a>5.2 JSTL的引入步骤</h3><blockquote>
<p>需要在JSP中引用JSTL标签库之后，才可以使用JSTL提供的标签</p>
</blockquote>
<ol>
<li><p>下载JSTL标签库的依赖jar  <a target="_blank" rel="noopener" href="https://mvnrepository.com/">https://mvnrepository.com/</a></p>
<ul>
<li><img src="/imgs/image-20211116110631598.png" class="lazyload" data-srcset="/imgs/image-20211116110631598.png" srcset="" alt="image-20211116110631598"></li>
<li><img src="/imgs/image-20211116110657149.png" class="lazyload" data-srcset="/imgs/image-20211116110657149.png" srcset="" alt="image-20211116110657149"></li>
</ul>
</li>
<li><p>将jar文件引入到当前web项目</p>
</li>
<li><p>在需要使用JSTL标签的JSP文件，通过<code>&lt;%@taglib%&gt;</code>引入JSTL标签库（JSTL包含多种标签，每种标签需要单独引入）</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--引入JSTL的核心标签库--&gt;</span><br><span class="line">&lt;%@ taglib prefix=<span class="string">&quot;c&quot;</span> uri=<span class="string">&quot;http://java.sun.com/jsp/jstl/core&quot;</span> %&gt;</span><br><span class="line">&lt;!--引入JSTL的转换标签库--&gt;</span><br><span class="line">&lt;%@ taglib prefix=<span class="string">&quot;fmt&quot;</span> uri=<span class="string">&quot;http://java.sun.com/jsp/jstl/fmt&quot;</span> %&gt;</span><br></pre></td></tr></table></figure></li>
</ol>
<h3 id="5-3-JSTL核心标签库"><a href="#5-3-JSTL核心标签库" class="headerlink" title="5.3 JSTL核心标签库"></a>5.3 JSTL核心标签库</h3><blockquote>
<p>c标签，主要用于完成JSP页面中逻辑控制&#x2F;流程控制</p>
<ul>
<li>分支</li>
<li>循环</li>
</ul>
</blockquote>
<h4 id="5-3-1-c-if"><a href="#5-3-1-c-if" class="headerlink" title="5.3.1 c:if"></a>5.3.1 c:if</h4><blockquote>
<p><code>&lt;c:if test=&quot;EL表达式条件&quot;&gt;</code></p>
<p>​      html</p>
<p><code>&lt;/c:if&gt;</code></p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;%--  如果test属性的el表达式返回的为<span class="literal">true</span>，则显示c:<span class="keyword">if</span>标签包含的HTML  --%&gt;</span><br><span class="line">&lt;c:<span class="keyword">if</span> test=<span class="string">&quot;$&#123;score &gt;= 60&#125;&quot;</span>&gt;</span><br><span class="line">    &lt;label style=<span class="string">&quot;color: green&quot;</span>&gt;通过&lt;/label&gt;</span><br><span class="line">&lt;/c:<span class="keyword">if</span>&gt;</span><br><span class="line">&lt;c:<span class="keyword">if</span> test=<span class="string">&quot;$&#123;score &lt; 60&#125;&quot;</span>&gt;</span><br><span class="line">    &lt;label style=<span class="string">&quot;color: red&quot;</span>&gt;不通过&lt;/label&gt;</span><br><span class="line">&lt;/c:<span class="keyword">if</span>&gt;</span><br></pre></td></tr></table></figure>

<h4 id="5-3-2-c-choose"><a href="#5-3-2-c-choose" class="headerlink" title="5.3.2 c:choose"></a>5.3.2 c:choose</h4><blockquote>
<p>c:choose为多分支语句，可以包含多个c:when和一个c:otherwise ,<br>寻找并执行第一个条件成立的c:when，如果所有c:when的条件都不成立则执行c:otherwise</p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;c:choose&gt;</span><br><span class="line">    &lt;c:when test=<span class="string">&quot;$&#123;score&gt;=90&#125;&quot;</span>&gt;</span><br><span class="line">        &lt;label style=<span class="string">&quot;color: green&quot;</span>&gt;优秀&lt;/label&gt;</span><br><span class="line">    &lt;/c:when&gt;</span><br><span class="line">    &lt;c:when test=<span class="string">&quot;$&#123;score&gt;=80&#125;&quot;</span>&gt;</span><br><span class="line">        &lt;label style=<span class="string">&quot;color: green&quot;</span>&gt;良好&lt;/label&gt;</span><br><span class="line">    &lt;/c:when&gt;</span><br><span class="line">    &lt;c:when test=<span class="string">&quot;$&#123;score&gt;=70&#125;&quot;</span>&gt;</span><br><span class="line">        &lt;label style=<span class="string">&quot;color: green&quot;</span>&gt;中等&lt;/label&gt;</span><br><span class="line">    &lt;/c:when&gt;</span><br><span class="line">    &lt;c:when test=<span class="string">&quot;$&#123;score&gt;=60&#125;&quot;</span>&gt;</span><br><span class="line">        &lt;label style=<span class="string">&quot;color: green&quot;</span>&gt;及格&lt;/label&gt;</span><br><span class="line">    &lt;/c:when&gt;</span><br><span class="line">    &lt;c:otherwise&gt;</span><br><span class="line">        &lt;label style=<span class="string">&quot;color: red&quot;</span>&gt;不及格&lt;/label&gt;</span><br><span class="line">    &lt;/c:otherwise&gt;</span><br><span class="line">&lt;/c:choose&gt;</span><br></pre></td></tr></table></figure>

<h4 id="5-3-3-c-forEach"><a href="#5-3-3-c-forEach" class="headerlink" title="5.3.3 c:forEach"></a>5.3.3 c:forEach</h4><blockquote>
<p>迭代标签、循环标签</p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"> &lt;%--  遍历传递过来的集合中的图书信息，显示在一个表格中  --%&gt;</span><br><span class="line">&lt;table align=<span class="string">&quot;center&quot;</span> border=<span class="string">&quot;1&quot;</span> cellspacing=<span class="string">&quot;0&quot;</span>&gt;</span><br><span class="line">    &lt;tr&gt;</span><br><span class="line">        &lt;th&gt;图书编号&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;图书名称&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;图书作者&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;图书价格&lt;/th&gt;</span><br><span class="line">    &lt;/tr&gt;</span><br><span class="line">    &lt;%--    获取传递过来的集合，集合中有几个图书信息，table就显示几行</span><br><span class="line">    items 指定要遍历的集合</span><br><span class="line">    <span class="keyword">var</span>  指定从集合中每次取出的数据的变量</span><br><span class="line">    begin 指定从集合中的哪个元素开始显示，<span class="number">0</span>表示第一个</span><br><span class="line">    end 指定取到哪个索引对应的集合元素</span><br><span class="line">    step 指定元素的间隔个数（默认为<span class="number">1</span>，依次取出所有元素）</span><br><span class="line">    --%&gt;</span><br><span class="line">    &lt;c:forEach items=<span class="string">&quot;$&#123;bookList&#125;&quot;</span> <span class="keyword">var</span>=<span class="string">&quot;book&quot;</span> begin=<span class="string">&quot;1&quot;</span> end=<span class="string">&quot;4&quot;</span> step=<span class="string">&quot;2&quot;</span>&gt;</span><br><span class="line">        &lt;tr&gt;</span><br><span class="line">            &lt;td&gt;$&#123;book.bookId&#125;&lt;/td&gt;</span><br><span class="line">            &lt;td&gt;$&#123;book.bookName&#125;&lt;/td&gt;</span><br><span class="line">            &lt;td&gt;$&#123;book.bookAuthor&#125;&lt;/td&gt;</span><br><span class="line">            &lt;td&gt;$&#123;book.bookPrice&#125;&lt;/td&gt;</span><br><span class="line">        &lt;/tr&gt;</span><br><span class="line">    &lt;/c:forEach&gt;</span><br><span class="line">&lt;/table&gt;</span><br></pre></td></tr></table></figure>

<h3 id="5-4-JSTL转换标签"><a href="#5-4-JSTL转换标签" class="headerlink" title="5.4 JSTL转换标签"></a>5.4 JSTL转换标签</h3><blockquote>
<p>fmt标签，提供了用于日期、数字等类型数据的格式转换的标签</p>
</blockquote>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;%--  格式化数字输出 --%&gt;</span><br><span class="line">&lt;fmt:formatNumber value=<span class="string">&quot;$&#123;num&#125;&quot;</span> pattern=<span class="string">&quot;#.0000&quot;</span>&gt;&lt;/fmt:formatNumber&gt;&lt;br/&gt;</span><br><span class="line">&lt;fmt:formatNumber value=<span class="string">&quot;$&#123;num&#125;&quot;</span> type=<span class="string">&quot;currency&quot;</span>&gt;&lt;/fmt:formatNumber&gt;&lt;br/&gt;</span><br><span class="line"></span><br><span class="line">&lt;%-- 格式化日期输出 --%&gt;</span><br><span class="line">&lt;fmt:formatDate value=<span class="string">&quot;$&#123;date&#125;&quot;</span> pattern=<span class="string">&quot;yyyy-MM-dd&quot;</span>&gt;&lt;/fmt:formatDate&gt;&lt;br/&gt;</span><br><span class="line">&lt;fmt:formatDate value=<span class="string">&quot;$&#123;date&#125;&quot;</span> pattern=<span class="string">&quot;hh:mm:ss&quot;</span>&gt;&lt;/fmt:formatDate&gt;&lt;br/&gt;</span><br><span class="line">&lt;fmt:formatDate value=<span class="string">&quot;$&#123;date&#125;&quot;</span> pattern=<span class="string">&quot;yyyy-MM-dd HH:mm:ss&quot;</span>&gt;&lt;/fmt:formatDate&gt;&lt;br/&gt;</span><br></pre></td></tr></table></figure>



<h2 id="六、Servlet和JSP的综合案例"><a href="#六、Servlet和JSP的综合案例" class="headerlink" title="六、Servlet和JSP的综合案例"></a>六、Servlet和JSP的综合案例</h2><blockquote>
<p>图书信息管理系统：管理员登录，对图书信息进行管理</p>
<ul>
<li>管理员登录</li>
<li>添加图书信息</li>
<li>图书信息列表</li>
<li>修改图书信息</li>
<li>删除图书信息</li>
</ul>
</blockquote>
<h3 id="6-1-书城后台管理系统业务流程"><a href="#6-1-书城后台管理系统业务流程" class="headerlink" title="6.1 书城后台管理系统业务流程"></a>6.1 书城后台管理系统业务流程</h3><p><img src="/imgs/image-20211116155037789.png" class="lazyload" data-srcset="/imgs/image-20211116155037789.png" srcset="" alt="image-20211116155037789"></p>
<h3 id="6-2-项目的MVC分层架构"><a href="#6-2-项目的MVC分层架构" class="headerlink" title="6.2 项目的MVC分层架构"></a>6.2 项目的MVC分层架构</h3><p>将项目中实现不同业务的代码进行分离:</p>
<ul>
<li><p>视图View — jsp负责进行客户端的页面呈现</p>
</li>
<li><p>控制器Controller — servlet负责接收用户请求，调用service进行处理，根据处理结果进行流程跳转</p>
</li>
<li><p>模型Model — service对数据的业务处理、DAO对数据的持久化操作</p>
</li>
</ul>
<h3 id="6-3-数据库设计"><a href="#6-3-数据库设计" class="headerlink" title="6.3 数据库设计"></a>6.3 数据库设计</h3><ol>
<li><p>根据项目业务功能抽象数据实体</p>
<ul>
<li>管理员</li>
<li>图书</li>
</ul>
</li>
<li><p>提取实体的数据项</p>
<ul>
<li>管理员（ID，登录名，登录密码，真实姓名，性别，电话，备注）</li>
<li>图书（编号，名称，作者，价格，封面图片，描述，库存，分类…）</li>
</ul>
</li>
<li><p>使用三范式约束的实体数据项（???）</p>
</li>
<li><p>E-R图</p>
</li>
<li><p>数据库建模</p>
</li>
<li><p>建库建表</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> database db_bookmall;</span><br><span class="line"></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> users(</span><br><span class="line">    user_id <span class="type">int</span> <span class="keyword">primary</span> key auto_increment,</span><br><span class="line">    user_name <span class="type">varchar</span>(<span class="number">40</span>) <span class="keyword">not</span> <span class="keyword">null</span> <span class="keyword">unique</span>,</span><br><span class="line">    user_pwd <span class="type">varchar</span>(<span class="number">40</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">    real_name <span class="type">varchar</span>(<span class="number">20</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">    user_gender <span class="type">char</span>(<span class="number">2</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">    user_tel <span class="type">char</span>(<span class="number">11</span>) <span class="keyword">not</span> <span class="keyword">null</span> <span class="keyword">unique</span>,</span><br><span class="line">    user_desc <span class="type">varchar</span>(<span class="number">200</span>)</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> books(</span><br><span class="line">     book_id <span class="type">char</span>(<span class="number">6</span>) <span class="keyword">primary</span> key,</span><br><span class="line">	 book_name <span class="type">varchar</span>(<span class="number">50</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">	 book_author <span class="type">varchar</span>(<span class="number">20</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">	 book_price <span class="type">DECIMAL</span>(<span class="number">10</span>,<span class="number">2</span>),</span><br><span class="line">	 book_img_path <span class="type">varchar</span>(<span class="number">100</span>) <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">	 book_desc <span class="type">varchar</span>(<span class="number">200</span>),</span><br><span class="line">     book_stcok <span class="type">int</span> <span class="keyword">not</span> <span class="keyword">null</span>,</span><br><span class="line">	 book_type <span class="type">int</span> <span class="keyword">not</span> <span class="keyword">null</span> </span><br><span class="line">);</span><br></pre></td></tr></table></figure></li>
</ol>
<h3 id="6-4-web项目环境搭建"><a href="#6-4-web项目环境搭建" class="headerlink" title="6.4 web项目环境搭建"></a>6.4 web项目环境搭建</h3><ol>
<li>创建web项目</li>
<li>搭建JDBC环境<ul>
<li>驱动</li>
<li>连接池</li>
<li>DBUtils</li>
</ul>
</li>
</ol>
<h3 id="6-5-数据库访问实现"><a href="#6-5-数据库访问实现" class="headerlink" title="6.5 数据库访问实现"></a>6.5 数据库访问实现</h3><h4 id="6-5-1-管理员登录的数据库操作"><a href="#6-5-1-管理员登录的数据库操作" class="headerlink" title="6.5.1 管理员登录的数据库操作"></a>6.5.1 管理员登录的数据库操作</h4><blockquote>
<ul>
<li>根据登录名查询用户信息 （根据用户名查询用户，将查询出来的用户的密码和输入的密码进行对别）</li>
</ul>
</blockquote>
<ol>
<li><p>创建实体类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.bookmall.ms.dto;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 管理员实体类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> userId;</span><br><span class="line">    <span class="keyword">private</span> String userName;</span><br><span class="line">    <span class="keyword">private</span> String userPwd;</span><br><span class="line">    <span class="keyword">private</span> String realName;</span><br><span class="line">    <span class="keyword">private</span> String userGender;</span><br><span class="line">    <span class="keyword">private</span> String userTel;</span><br><span class="line">    <span class="keyword">private</span> String userDesc;</span><br><span class="line">	<span class="comment">//....</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>创建DAO类实现数据库操作</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.bookmall.ms.dao;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.dto.User;</span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.utils.DruidUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.dbutils.QueryRunner;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.dbutils.handlers.BeanHandler;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 用于实现管理员的数据库操作</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDAO</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据管理员登录名查询管理员信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> userName</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> User <span class="title function_">selectUserByUserName</span><span class="params">(String userName)</span>&#123;</span><br><span class="line">        <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select user_id userId,user_name userName,user_pwd userPwd,real_name realName,user_gender userGender,user_tel userTel,user_desc userDesc from users where user_name=?&quot;</span>;</span><br><span class="line">            <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">            user = queryRunner.query(sql, <span class="keyword">new</span> <span class="title class_">BeanHandler</span>&lt;User&gt;(User.class));</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> user;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
<h4 id="6-5-2-图书管理的数据库操作"><a href="#6-5-2-图书管理的数据库操作" class="headerlink" title="6.5.2 图书管理的数据库操作"></a>6.5.2 图书管理的数据库操作</h4><blockquote>
<ul>
<li>添加图书信息</li>
<li>查询所有图书信息</li>
<li>根据图书ID删除一个图书信息</li>
<li>根据图书ID查询一个图书信息</li>
<li>根据图书ID修改一个图书信息</li>
</ul>
</blockquote>
<ol>
<li><p>创建图书实体类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.bookmall.ms.dto;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 图书信息实体类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Book</span> &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">private</span> String bookId;</span><br><span class="line">    <span class="keyword">private</span> String bookName;</span><br><span class="line">    <span class="keyword">private</span> String bookAuthor;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">double</span> bookPrice;</span><br><span class="line">    <span class="keyword">private</span> String bookImgPath;</span><br><span class="line">    <span class="keyword">private</span> String bookDesc;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> bookStock;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> bookType;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>创建DAO类完成数据库操作</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.bookmall.ms.dao;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.dto.Book;</span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.utils.DruidUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.dbutils.QueryRunner;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.dbutils.handlers.BeanHandler;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.dbutils.handlers.BeanListHandler;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.sql.SQLException;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 完成图书信息的数据库操作</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookDAO</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 添加图书信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">insertBook</span><span class="params">(Book book)</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;insert into books(book_id,book_name,book_author,book_price,book_img_path,book_desc,book_stcok,book_type) values(?,?,?,?,?,?,?,?)&quot;</span>;</span><br><span class="line">            <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">            <span class="comment">//给SQL中的参数赋值</span></span><br><span class="line">            Object[] params = &#123;book.getBookId(),book.getBookName(),book.getBookAuthor(),book.getBookPrice(),book.getBookImgPath(),book.getBookDesc(),book.getBookStock(),book.getBookType()&#125;;</span><br><span class="line">            i = queryRunner.update(sql, params);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询所有图书信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Book&gt; <span class="title function_">selectBooks</span><span class="params">()</span>&#123;</span><br><span class="line">        List&lt;Book&gt; bookList = <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select book_id bookId,book_name bookName,book_author bookAuthor,book_price bookPrice,book_img_path bookImgPath,book_desc bookDesc,book_stcok bookStock,book_type bookType from books&quot;</span>;</span><br><span class="line">            <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">            bookList = queryRunner.query(sql, <span class="keyword">new</span> <span class="title class_">BeanListHandler</span>&lt;Book&gt;(Book.class));</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> bookList;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据图书ID删除一个图书信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookId</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">deleteBook</span><span class="params">(String bookId)</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;delete from books where book_id=?&quot;</span>;</span><br><span class="line">            <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">            i = queryRunner.update(sql, bookId);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据图书ID查询一个图书信息</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> Book <span class="title function_">selectBookByBookId</span><span class="params">(String bookId)</span>&#123;</span><br><span class="line">        <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select book_id bookId,book_name bookName,book_author bookAuthor,book_price bookPrice,book_img_path bookImgPath,book_desc bookDesc,book_stcok bookStock,book_type bookType from books where book_id=?&quot;</span>;</span><br><span class="line">            <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">            book = queryRunner.query(sql, <span class="keyword">new</span> <span class="title class_">BeanHandler</span>&lt;Book&gt;(Book.class),bookId);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> book;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据图书ID修改一个图书信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">updateBook</span><span class="params">(Book book)</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;update books set book_name=?,book_author=?,book_price=?,book_img_path=?,book_desc=?,book_stcok=?,book_type=? where book_id=?&quot;</span>;</span><br><span class="line">            <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">            Object[] params = &#123;book.getBookName(),book.getBookAuthor(),book.getBookPrice(),book.getBookImgPath(),book.getBookDesc(),book.getBookStock(),book.getBookType(),book.getBookId()&#125;;</span><br><span class="line">            i = queryRunner.update(sql, params);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
<h3 id="6-6-网页设计"><a href="#6-6-网页设计" class="headerlink" title="6.6 网页设计"></a>6.6 网页设计</h3><ul>
<li>login.html</li>
<li>index.html</li>
<li>prompt.html</li>
<li>book-add.html</li>
<li>book-list.html</li>
<li>book-modify.html</li>
</ul>
<h3 id="6-7-业务层实现"><a href="#6-7-业务层实现" class="headerlink" title="6.7 业务层实现"></a>6.7 业务层实现</h3><h4 id="6-7-1-管理员登录业务"><a href="#6-7-1-管理员登录业务" class="headerlink" title="6.7.1 管理员登录业务"></a>6.7.1 管理员登录业务</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.bookmall.ms.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.dao.UserDAO;</span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.dto.User;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 管理员相关业务实现</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 管理员登录业务：根据账号密码验证管理登录，验证通过返回user对象，否则返回null</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> userName</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> userPwd</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> User <span class="title function_">checkLogin</span><span class="params">(String userName, String userPwd)</span>&#123;</span><br><span class="line">        <span class="comment">//1.根据userName查询管理员信息</span></span><br><span class="line">        <span class="type">UserDAO</span> <span class="variable">userDAO</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UserDAO</span>();</span><br><span class="line">        <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> userDAO.selectUserByUserName(userName);</span><br><span class="line">        <span class="comment">//2.判断密码</span></span><br><span class="line">        <span class="keyword">if</span>(user != <span class="literal">null</span> &amp;&amp; user.getUserPwd() .equals(userPwd))&#123;</span><br><span class="line">            <span class="keyword">return</span> user;</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="6-7-2-图书管理业务实现"><a href="#6-7-2-图书管理业务实现" class="headerlink" title="6.7.2 图书管理业务实现"></a>6.7.2 图书管理业务实现</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.bookmall.ms.service;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.dao.BookDAO;</span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.dto.Book;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 图书管理的业务实现</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookService</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">BookDAO</span> <span class="variable">bookDAO</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BookDAO</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 添加图书业务实现</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">saveBook</span><span class="params">(Book book)</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> bookDAO.insertBook(book);</span><br><span class="line">        <span class="keyword">return</span> i&gt;<span class="number">0</span>?<span class="literal">true</span>:<span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除图书业务实现</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookId</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">deleteBook</span><span class="params">(String bookId)</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> bookDAO.deleteBook(bookId);</span><br><span class="line">        <span class="keyword">return</span> i&gt;<span class="number">0</span>?<span class="literal">true</span>:<span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据ID查询一个图书的业务实现</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> bookId</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> Book <span class="title function_">getBook</span><span class="params">(String bookId)</span>&#123;</span><br><span class="line">        <span class="type">Book</span> <span class="variable">book</span> <span class="operator">=</span> bookDAO.selectBookByBookId(bookId);</span><br><span class="line">        <span class="keyword">return</span> book;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 修改图书业务实现</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> book</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">modifyBook</span><span class="params">(Book book)</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> bookDAO.updateBook(book);</span><br><span class="line">        <span class="keyword">return</span> i&gt;<span class="number">0</span>?<span class="literal">true</span>:<span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询所有图书信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;Book&gt; <span class="title function_">listBooks</span><span class="params">()</span>&#123;</span><br><span class="line">        List&lt;Book&gt; bookList = bookDAO.selectBooks();</span><br><span class="line">        <span class="keyword">return</span> bookList;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="6-8-功能流程实现"><a href="#6-8-功能流程实现" class="headerlink" title="6.8 功能流程实现"></a>6.8 功能流程实现</h3><h4 id="6-8-1-创建JSP及Servlet类"><a href="#6-8-1-创建JSP及Servlet类" class="headerlink" title="6.8.1 创建JSP及Servlet类"></a>6.8.1 创建JSP及Servlet类</h4><ol>
<li>在项目创建所需的JSP文件，将设计好的HTML整合到JSP中</li>
<li>创建servlets包，在servlets中创建业务流程实现所需的Servlet类</li>
</ol>
<h4 id="6-8-2-管理员登录"><a href="#6-8-2-管理员登录" class="headerlink" title="6.8.2 管理员登录"></a>6.8.2 管理员登录</h4><table>
<thead>
<tr>
<th><code>login.jsp</code>  —&gt;   提交账号和密码到LoginCheckServlet</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116200041611.png" class="lazyload" data-srcset="/imgs/image-20211116200041611.png" srcset="" alt="image-20211116200041611"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>LoginCheckServlet</code>  —&gt;  接收账号和密码进行校验，根据校验跳转</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116200652142.png" class="lazyload" data-srcset="/imgs/image-20211116200652142.png" srcset="" alt="image-20211116200652142"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>login.jsp</code> —&gt; 显示登录失败时传递的提示信息</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116200932491.png" class="lazyload" data-srcset="/imgs/image-20211116200932491.png" srcset="" alt="image-20211116200932491"></td>
</tr>
</tbody></table>
<h4 id="6-8-3-添加图书"><a href="#6-8-3-添加图书" class="headerlink" title="6.8.3 添加图书"></a>6.8.3 添加图书</h4><table>
<thead>
<tr>
<th><code>index.jsp</code> —&gt; 点击添加图书菜单，显示book-add.jsp</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116202227915.png" class="lazyload" data-srcset="/imgs/image-20211116202227915.png" srcset="" alt="image-20211116202227915"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>book-add.jsp</code> —&gt; 提交数据到BookSaveServlet（表单中有文件上传）</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116202457419.png" class="lazyload" data-srcset="/imgs/image-20211116202457419.png" srcset="" alt="image-20211116202457419"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>BookSaveServlet</code> —&gt; 在Servlet前添加 <code>@MultipartConfig</code>注解</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116204213194.png" class="lazyload" data-srcset="/imgs/image-20211116204213194.png" srcset="" alt="image-20211116204213194"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>prompt.jsp</code> —&gt; 显示提示信息</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116203906248.png" class="lazyload" data-srcset="/imgs/image-20211116203906248.png" srcset="" alt="image-20211116203906248"></td>
</tr>
</tbody></table>
<p>注意：如果添加的中文出现乱码则添加编码过滤器</p>
<h4 id="6-8-4-图书列表"><a href="#6-8-4-图书列表" class="headerlink" title="6.8.4 图书列表"></a>6.8.4 图书列表</h4><table>
<thead>
<tr>
<th><code>index.jsp</code> —-&gt; 点击图书列表向BookListServlet发送请求</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116223248436.png" class="lazyload" data-srcset="/imgs/image-20211116223248436.png" srcset="" alt="image-20211116223248436"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>BookListServlet</code> —&gt;查询图书信息，转发传递到book-list.jsp</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116223450672.png" class="lazyload" data-srcset="/imgs/image-20211116223450672.png" srcset="" alt="image-20211116223450672"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>book-list.jsp</code> —&gt; JSTL+EL遍历显示图书信息 （需要在项目中引入jstl的2个jar文件）</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116224720659.png" class="lazyload" data-srcset="/imgs/image-20211116224720659.png" srcset="" alt="image-20211116224720659"></td>
</tr>
</tbody></table>
<h4 id="6-8-5-删除图书"><a href="#6-8-5-删除图书" class="headerlink" title="6.8.5 删除图书"></a>6.8.5 删除图书</h4><table>
<thead>
<tr>
<th><code>book-list.jsp</code>—&gt; 显示图书列表时，将图书id和删除按钮绑定，点击删除时将当前图书的id传递到BookDeleteServlet</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116231444817.png" class="lazyload" data-srcset="/imgs/image-20211116231444817.png" srcset="" alt="image-20211116231444817"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>BookDeleteServlet</code> —&gt; 获取图书ID，删除图书信息，进行提示</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116231154693.png" class="lazyload" data-srcset="/imgs/image-20211116231154693.png" srcset="" alt="image-20211116231154693"></td>
</tr>
</tbody></table>
<h4 id="6-8-6-修改图书"><a href="#6-8-6-修改图书" class="headerlink" title="6.8.6 修改图书"></a>6.8.6 修改图书</h4><table>
<thead>
<tr>
<th><code>book-list.jsp</code> —&gt; 点击修改，将图书ID传递到BookQueryServlet</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116235257984.png" class="lazyload" data-srcset="/imgs/image-20211116235257984.png" srcset="" alt="image-20211116235257984"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>BookQueryServlet</code> —&gt; 查询要修改的图书的原始信息</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211116235646132.png" class="lazyload" data-srcset="/imgs/image-20211116235646132.png" srcset="" alt="image-20211116235646132"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>book-modify.jsp</code> —&gt; 显示BookQueryServlet传递的图书的原始信息,修改之后提交到BookUpdateServlet<br/>红色标注表示显示图书原始信息、紫色标注表示提交修改</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211117001900308.png" class="lazyload" data-srcset="/imgs/image-20211117001900308.png" srcset="" alt="image-20211117001900308"></td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><code>BookUpdateServlet</code>—&gt; 接收修改后的数据，执行修改，并提示</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211117002311401.png" class="lazyload" data-srcset="/imgs/image-20211117002311401.png" srcset="" alt="image-20211117002311401"></td>
</tr>
</tbody></table>
<h2 id="七、分页功能实现"><a href="#七、分页功能实现" class="headerlink" title="七、分页功能实现"></a>七、分页功能实现</h2><h3 id="7-1-分页概念"><a href="#7-1-分页概念" class="headerlink" title="7.1 分页概念"></a>7.1 分页概念</h3><blockquote>
<p>分页是web应用开发中非常重要的一个业务实现。数据库中的数据可能很多（成千上万、几十万、上百万都又可能），不能将这些数据全部查询出来并显示到列表页面。一般我们需要为用户提供<code>翻页功能</code>，例如一次显示10行&#x2F;20行，然后点击下一页查看接下来的10行&#x2F;20行。</p>
</blockquote>
<p><img src="/imgs/image-20211117010033508.png" class="lazyload" data-srcset="/imgs/image-20211117010033508.png" srcset="" alt="image-20211117010033508"></p>
<h3 id="7-2-分页实现思路"><a href="#7-2-分页实现思路" class="headerlink" title="7.2 分页实现思路"></a>7.2 分页实现思路</h3><p><img src="/imgs/image-20211117013457645.png" class="lazyload" data-srcset="/imgs/image-20211117013457645.png" srcset="" alt="image-20211117013457645"></p>
<h3 id="7-3-分页代码实现"><a href="#7-3-分页代码实现" class="headerlink" title="7.3 分页代码实现"></a>7.3 分页代码实现</h3><h4 id="7-3-1-BookDAO"><a href="#7-3-1-BookDAO" class="headerlink" title="7.3.1 BookDAO"></a>7.3.1 BookDAO</h4><ul>
<li><p>分页查询数据</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 分页查询图书信息</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> start 查询数据的起始行索引</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> limit 最多返回的数据记录数（每页显示的条数）</span></span><br><span class="line"><span class="comment">* <span class="doctag">@return</span> 返回的集合中只包含一页的数据</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> List&lt;Book&gt; <span class="title function_">selectBooks</span><span class="params">(<span class="type">int</span> start,<span class="type">int</span> limit)</span>&#123;</span><br><span class="line">    List&lt;Book&gt; bookList = <span class="literal">null</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select book_id bookId,book_name bookName,book_author bookAuthor,book_price bookPrice,book_img_path bookImgPath,book_desc bookDesc,book_stcok bookStock,book_type bookType from books limit ?,?&quot;</span>;</span><br><span class="line">        <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">        bookList = </span><br><span class="line">            queryRunner.query(sql, <span class="keyword">new</span> <span class="title class_">BeanListHandler</span>&lt;Book&gt;(Book.class),start,limit);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> bookList;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>查询总记录数</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 查询图书的总记录数</span></span><br><span class="line"><span class="comment">* <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">long</span> <span class="title function_">selectBookCount</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="type">long</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select count(1) from books&quot;</span>;</span><br><span class="line">        <span class="type">QueryRunner</span> <span class="variable">queryRunner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">QueryRunner</span>(DruidUtils.getDataSource());</span><br><span class="line">        count = queryRunner.query(sql,<span class="keyword">new</span> <span class="title class_">ScalarHandler</span>&lt;Long&gt;());</span><br><span class="line">    &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> count;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="7-3-2-BookService"><a href="#7-3-2-BookService" class="headerlink" title="7.3.2 BookService"></a>7.3.2 BookService</h4><ul>
<li><p>根据页码、每页条数查询当前页的数据</p>
</li>
<li><p>根据每页条数计算总页数</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 分页查询图书信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> pageNum 页码</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> pageSize 每页显示的条数</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> List&lt;Book&gt; <span class="title function_">listBooksByPage</span><span class="params">( <span class="type">int</span> pageNum,<span class="type">int</span> pageSize)</span>&#123;</span><br><span class="line">    <span class="type">int</span> <span class="variable">start</span> <span class="operator">=</span> (pageNum-<span class="number">1</span>)*pageSize;</span><br><span class="line">    <span class="type">int</span> <span class="variable">limit</span> <span class="operator">=</span> pageSize;</span><br><span class="line">    List&lt;Book&gt; bookList = bookDAO.selectBooks(start,limit);</span><br><span class="line">    <span class="keyword">return</span> bookList;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询图书总页数</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> pageSize 每页显示的条数</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">getPageCount</span><span class="params">(<span class="type">int</span> pageSize)</span>&#123;</span><br><span class="line">    <span class="comment">//1.查询总记录</span></span><br><span class="line">    <span class="type">long</span> <span class="variable">count</span> <span class="operator">=</span> bookDAO.selectBookCount();</span><br><span class="line">    <span class="comment">//2.根据总记录数和每页显示的条数，计算总页数</span></span><br><span class="line">    <span class="type">long</span> <span class="variable">pageCount</span> <span class="operator">=</span> count%pageSize == <span class="number">0</span> ? count/pageSize: count/pageSize+<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">return</span> (<span class="type">int</span>)pageCount;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="7-3-3-BookListServlet"><a href="#7-3-3-BookListServlet" class="headerlink" title="7.3.3 BookListServlet"></a>7.3.3 BookListServlet</h4><p>1.接收页码 pageNum</p>
<p>2.定义每页显示条数 pageSize</p>
<p>3.查询当前页数据 bookList</p>
<p>4.查询总记录数 pageCount</p>
<p>5.转发到列表页面</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.bookmall.ms.servlets;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.dto.Book;</span><br><span class="line"><span class="keyword">import</span> com.qfedu.bookmall.ms.service.BookService;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.ServletException;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.annotation.WebServlet;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServlet;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>  分页查询图书信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@WebServlet(&quot;/BookListServlet&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookListServlet</span> <span class="keyword">extends</span> <span class="title class_">HttpServlet</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doGet</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> </span><br><span class="line">        <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        doPost(request, response);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doPost</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> </span><br><span class="line">        <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        <span class="comment">//1.接收客户端传递的页码</span></span><br><span class="line">        <span class="comment">//  (如果客户端没有传递页码，则默认页码为1，如果传递了则使用客户端传递的页码)</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">num</span> <span class="operator">=</span> request.getParameter(<span class="string">&quot;pageNum&quot;</span>);</span><br><span class="line">        <span class="type">int</span> <span class="variable">pageNum</span> <span class="operator">=</span> num==<span class="literal">null</span>? <span class="number">1</span>: Integer.parseInt( num );</span><br><span class="line">        <span class="comment">//2.定义pageSize</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">pageSize</span> <span class="operator">=</span> <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//3.调用BookService查询这一页的图书信息</span></span><br><span class="line">        <span class="type">BookService</span> <span class="variable">bookService</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BookService</span>();</span><br><span class="line">        List&lt;Book&gt; bookList = bookService.listBooksByPage(pageNum,pageSize);</span><br><span class="line">        <span class="comment">//4.调用BookService查询图书的总页数</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">pageCount</span> <span class="operator">=</span> bookService.getPageCount(pageSize);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">//5.将查询到的当前页数据的集合、当前页码、总页数  转发到book-list.jsp</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;bookList&quot;</span>,bookList);</span><br><span class="line">        request.setAttribute(<span class="string">&quot;pageNum&quot;</span>,pageNum);</span><br><span class="line">        request.setAttribute(<span class="string">&quot;pageCount&quot;</span>,pageCount);</span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;book-list.jsp&quot;</span>).forward(request,response);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="7-4-book-list-jsp"><a href="#7-4-book-list-jsp" class="headerlink" title="7.4 book-list.jsp"></a>7.4 book-list.jsp</h4><figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line">&lt;%@ page contentType=<span class="string">&quot;text/html;charset=UTF-8&quot;</span> language=<span class="string">&quot;java&quot;</span> %&gt;</span><br><span class="line">&lt;%@ taglib prefix=<span class="string">&quot;c&quot;</span> uri=<span class="string">&quot;http://java.sun.com/jsp/jstl/core&quot;</span> %&gt;</span><br><span class="line">&lt;%@ taglib prefix=<span class="string">&quot;fmt&quot;</span> uri=<span class="string">&quot;http://java.sun.com/jsp/jstl/fmt&quot;</span> %&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=<span class="string">&quot;utf-8&quot;</span>&gt;</span><br><span class="line">    &lt;title&gt;&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">  &lt;h3&gt;图书信息列表&lt;/h3&gt;</span><br><span class="line">    &lt;table width=<span class="string">&quot;90%&quot;</span> align=<span class="string">&quot;center&quot;</span> border=<span class="string">&quot;1&quot;</span> cellspacing=<span class="string">&quot;0&quot;</span>&gt;</span><br><span class="line">      &lt;tr&gt;</span><br><span class="line">        &lt;th&gt;编号&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;封面&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;名称&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;作者&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;价格&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;库存&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;描述&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;类型&lt;/th&gt;</span><br><span class="line">        &lt;th&gt;操作&lt;/th&gt;</span><br><span class="line">      &lt;/tr&gt;</span><br><span class="line">      &lt;c:forEach items=<span class="string">&quot;$&#123;bookList&#125;&quot;</span> <span class="keyword">var</span>=<span class="string">&quot;book&quot;</span>&gt;</span><br><span class="line">        &lt;tr&gt;</span><br><span class="line">          &lt;td&gt;$&#123;book.bookId&#125;&lt;/td&gt;</span><br><span class="line">          &lt;td&gt;&lt;img src=<span class="string">&quot;$&#123;book.bookImgPath&#125;&quot;</span> height=<span class="string">&quot;50&quot;</span>&gt;&lt;/td&gt;</span><br><span class="line">          &lt;td&gt;$&#123;book.bookName&#125;&lt;/td&gt;</span><br><span class="line">          &lt;td&gt;$&#123;book.bookAuthor&#125;&lt;/td&gt;</span><br><span class="line">          &lt;td&gt;&lt;fmt:formatNumber value=<span class="string">&quot;$&#123;book.bookPrice&#125;&quot;</span> type=<span class="string">&quot;currency&quot;</span> /&gt;&lt;/td&gt;</span><br><span class="line">          &lt;td&gt;$&#123;book.bookStock&#125;&lt;/td&gt;</span><br><span class="line">          &lt;td&gt;$&#123;book.bookDesc&#125;&lt;/td&gt;</span><br><span class="line">          &lt;td&gt;</span><br><span class="line">            &lt;c:<span class="keyword">if</span> test=<span class="string">&quot;$&#123;book.bookType ==1&#125;&quot;</span>&gt;原创&lt;/c:<span class="keyword">if</span>&gt;</span><br><span class="line">            &lt;c:<span class="keyword">if</span> test=<span class="string">&quot;$&#123;book.bookType ==2&#125;&quot;</span>&gt;翻译&lt;/c:<span class="keyword">if</span>&gt;</span><br><span class="line">          &lt;/td&gt;</span><br><span class="line">          &lt;td&gt;</span><br><span class="line">            &lt;a href=<span class="string">&quot;BookQueryServlet?bookId=$&#123;book.bookId&#125;&quot;</span>&gt;修改&lt;/a&gt;</span><br><span class="line">            &lt;a href=<span class="string">&quot;BookDeleteServlet?bookId=$&#123;book.bookId&#125;&quot;</span></span><br><span class="line">               onclick=<span class="string">&quot;javascript:return confirm(&#x27;你确定删除吗？&#x27;)&quot;</span>&gt;删除&lt;/a&gt;</span><br><span class="line">          &lt;/td&gt;</span><br><span class="line">        &lt;/tr&gt;</span><br><span class="line">      &lt;/c:forEach&gt;</span><br><span class="line">      &lt;!--  显示分页效果及页码切换 --&gt;</span><br><span class="line">      &lt;tr height=<span class="string">&quot;50&quot;</span>&gt;</span><br><span class="line">        &lt;td colspan=<span class="string">&quot;9&quot;</span> align=<span class="string">&quot;center&quot;</span>&gt;</span><br><span class="line">            &lt;!--显示首页、上一页：如果当前页就是第一页，则不显示超链接--&gt;</span><br><span class="line">            &lt;c:<span class="keyword">if</span> test=<span class="string">&quot;$&#123;pageNum ==1 &#125;&quot;</span>&gt;</span><br><span class="line">                &lt;label style=<span class="string">&quot;color:gray&quot;</span>&gt;首页&lt;/label&gt;</span><br><span class="line">                &lt;label style=<span class="string">&quot;color:gray&quot;</span>&gt;上一页&lt;/label&gt;</span><br><span class="line">            &lt;/c:<span class="keyword">if</span>&gt;</span><br><span class="line">            &lt;c:<span class="keyword">if</span> test=<span class="string">&quot;$&#123;pageNum &gt; 1 &#125;&quot;</span>&gt;</span><br><span class="line">                &lt;a href=<span class="string">&quot;BookListServlet?pageNum=1&quot;</span>&gt;首页&lt;/a&gt;</span><br><span class="line">              &lt;a href=<span class="string">&quot;BookListServlet?pageNum=$&#123;pageNum-1&#125;&quot;</span>&gt;上一页&lt;/a&gt;</span><br><span class="line">            &lt;/c:<span class="keyword">if</span>&gt;</span><br><span class="line"></span><br><span class="line">            &lt;!-- 显示页码 和总页数 --&gt;</span><br><span class="line">            当前第$&#123;pageNum&#125;页/共$&#123;pageCount&#125;页</span><br><span class="line"></span><br><span class="line">            &lt;!-- 显示下一页 和 尾页 --&gt;</span><br><span class="line">            &lt;c:<span class="keyword">if</span> test=<span class="string">&quot;$&#123;pageNum &lt; pageCount&#125;&quot;</span>&gt;</span><br><span class="line">              &lt;a href=<span class="string">&quot;BookListServlet?pageNum=$&#123;pageNum+1&#125;&quot;</span>&gt;下一页&lt;/a&gt;</span><br><span class="line">              &lt;a href=<span class="string">&quot;BookListServlet?pageNum=$&#123;pageCount&#125;&quot;</span>&gt;尾页&lt;/a&gt;</span><br><span class="line">            &lt;/c:<span class="keyword">if</span>&gt;</span><br><span class="line">            &lt;c:<span class="keyword">if</span> test=<span class="string">&quot;$&#123;pageNum == pageCount&#125;&quot;</span>&gt;</span><br><span class="line">                &lt;label style=<span class="string">&quot;color:gray&quot;</span>&gt;下一页&lt;/label&gt;</span><br><span class="line">                &lt;label style=<span class="string">&quot;color:gray&quot;</span>&gt;尾页&lt;/label&gt;</span><br><span class="line">            &lt;/c:<span class="keyword">if</span>&gt;</span><br><span class="line">        &lt;/td&gt;</span><br><span class="line">      &lt;/tr&gt;</span><br><span class="line">    &lt;/table&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<h3 id="7-4-PageHelper封装"><a href="#7-4-PageHelper封装" class="headerlink" title="7.4 PageHelper封装"></a>7.4 PageHelper封装</h3><blockquote>
<p>思考：</p>
<ol>
<li>分页操作在Service查询页面数据及总页码都属同一个分页业务，为什么要携程两个方法呢？能不能在一个方法完成呢？</li>
<li>Servlet类主要负责流程控制，在上述代码实现过程中也涉及到了分页业务，不可理。该如何解决呢？</li>
</ol>
</blockquote>
<h4 id="7-4-1-PageHelper封装思路"><a href="#7-4-1-PageHelper封装思路" class="headerlink" title="7.4.1 PageHelper封装思路"></a>7.4.1 PageHelper封装思路</h4><p><img src="/imgs/image-20211117023144522.png" class="lazyload" data-srcset="/imgs/image-20211117023144522.png" srcset="" alt="image-20211117023144522"></p>
<h4 id="7-4-2-创建分页帮助类PageHelper"><a href="#7-4-2-创建分页帮助类PageHelper" class="headerlink" title="7.4.2  创建分页帮助类PageHelper"></a>7.4.2  创建分页帮助类PageHelper</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.qfedu.bookmall.ms.utils;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 分页帮助类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PageHelper</span>&lt;T&gt; &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//存放页面数据的List集合</span></span><br><span class="line">    <span class="keyword">public</span> List&lt;T&gt; list;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//存放当前页码</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> pageNum;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//存放总页数</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> pageCount;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//无参构造器</span></span><br><span class="line">    <span class="comment">//全参构造器</span></span><br><span class="line">    <span class="comment">//get和set</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="7-4-3-BookService"><a href="#7-4-3-BookService" class="headerlink" title="7.4.3 BookService"></a>7.4.3 BookService</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 分页查询图书信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> pageNum 页码</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> pageSize 每页显示的条数</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"><span class="keyword">public</span> PageHelper&lt;Book&gt; <span class="title function_">listBooksByPage</span><span class="params">( <span class="type">int</span> pageNum,<span class="type">int</span> pageSize)</span>&#123;</span><br><span class="line">    <span class="comment">//1.查询当前页码的数据</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">start</span> <span class="operator">=</span> (pageNum-<span class="number">1</span>)*pageSize;</span><br><span class="line">    <span class="type">int</span> <span class="variable">limit</span> <span class="operator">=</span> pageSize;</span><br><span class="line">    List&lt;Book&gt; bookList = bookDAO.selectBooks(start,limit);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//2.查询并计算图书总页数</span></span><br><span class="line">    <span class="comment">//a.查询总记录</span></span><br><span class="line">    <span class="type">long</span> <span class="variable">count</span> <span class="operator">=</span> bookDAO.selectBookCount();</span><br><span class="line">    <span class="comment">//b.根据总记录数和每页显示的条数，计算总页数</span></span><br><span class="line">    <span class="type">long</span> <span class="variable">pageCount</span> <span class="operator">=</span> count%pageSize == <span class="number">0</span> ? count/pageSize: count/pageSize+<span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//3.将分页数据都放到一个PageHelper对象</span></span><br><span class="line">    PageHelper&lt;Book&gt; bookPageHelper = <span class="keyword">new</span> <span class="title class_">PageHelper</span>&lt;Book&gt;(bookList, pageNum, (<span class="type">int</span>)pageCount);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> bookPageHelper;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="7-4-4-BookListServlet"><a href="#7-4-4-BookListServlet" class="headerlink" title="7.4.4 BookListServlet"></a>7.4.4 BookListServlet</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>  分页查询图书信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Author</span> 千锋涛哥</span></span><br><span class="line"><span class="comment"> * 公众号： Java架构栈</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@WebServlet(&quot;/BookListServlet&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookListServlet</span> <span class="keyword">extends</span> <span class="title class_">HttpServlet</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doGet</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        doPost(request, response);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">doPost</span><span class="params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="keyword">throws</span> ServletException, IOException &#123;</span><br><span class="line">        <span class="comment">//1.接收客户端传递的页码</span></span><br><span class="line">        <span class="comment">//  (如果客户端没有传递页码，则默认页码为1，如果传递了则使用客户端传递的页码)</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">num</span> <span class="operator">=</span> request.getParameter(<span class="string">&quot;pageNum&quot;</span>);</span><br><span class="line">        <span class="type">int</span> <span class="variable">pageNum</span> <span class="operator">=</span> num==<span class="literal">null</span>? <span class="number">1</span>: Integer.parseInt( num );</span><br><span class="line">        <span class="comment">//2.定义pageSize</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">pageSize</span> <span class="operator">=</span> <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//3.调用BookService查询这一页的图书信息</span></span><br><span class="line">        <span class="type">BookService</span> <span class="variable">bookService</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">BookService</span>();</span><br><span class="line">        PageHelper&lt;Book&gt; bookPageHelper = bookService.listBooksByPage(pageNum, pageSize);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//5.将查询到的bookPageHelper(当前页数据的集合、当前页码、总页数)  转发到book-list.jsp</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;bookPageHelper&quot;</span>,bookPageHelper);</span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;book-list.jsp&quot;</span>).forward(request,response);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="7-4-5-book-list-jsp"><a href="#7-4-5-book-list-jsp" class="headerlink" title="7.4.5 book-list.jsp"></a>7.4.5 book-list.jsp</h4><table>
<thead>
<tr>
<th><code>book-list.jsp</code> 页面的数据都从<code>bookPageHelper</code>对象获取</th>
</tr>
</thead>
<tbody><tr>
<td><img src="/imgs/image-20211117024307271.png" class="lazyload" data-srcset="/imgs/image-20211117024307271.png" srcset="" alt="image-20211117024307271"></td>
</tr>
</tbody></table>

  </div>
  
  
    
    <div class='footer'>
       <!-- 参考资料、相关资料等 -->
      
       <!-- 相关文章 -->
      
      <!-- 版权声明组件 -->
      
      <!-- 打赏组件 -->
      
    </div>
  
  
    


  <div class='article-meta' id="bottom">
    <div class='new-meta-box'>
      
        
          <div class="new-meta-item date" itemprop="dateModified" datetime="2024-01-07T23:46:22+08:00">
  <a class='notlink'>
    <i class="fa-solid fa-edit fa-fw" aria-hidden="true"></i>
    <p>更新于：Jan 7, 2024</p>
  </a>
</div>

        
      
        
          

        
      
        
          
  <div class="new-meta-item share -mob-share-list">
  <div class="-mob-share-list share-body">
    
      
        <a class="-mob-share-qq" title="" rel="external nofollow noopener noreferrer noopener"
          
          target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://8.219.11.28/2024/02/23/%E5%8D%95%E4%BD%93-JSP/&title= - 欢迎来到我的个人博客~&summary="
          
          >
          
            <img src="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/qq.png" class="lazyload" data-srcset="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/qq.png" srcset="">
          
        </a>
      
    
      
        <a class="-mob-share-qzone" title="" rel="external nofollow noopener noreferrer noopener"
          
          target="_blank" href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=http://8.219.11.28/2024/02/23/%E5%8D%95%E4%BD%93-JSP/&title= - 欢迎来到我的个人博客~&summary="
          
          >
          
            <img src="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/qzone.png" class="lazyload" data-srcset="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/qzone.png" srcset="">
          
        </a>
      
    
      
        <a class="-mob-share-weibo" title="" rel="external nofollow noopener noreferrer noopener"
          
          target="_blank" href="http://service.weibo.com/share/share.php?url=http://8.219.11.28/2024/02/23/%E5%8D%95%E4%BD%93-JSP/&title= - 欢迎来到我的个人博客~&summary="
          
          >
          
            <img src="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/weibo.png" class="lazyload" data-srcset="https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/logo/128/weibo.png" srcset="">
          
        </a>
      
    
      
    
      
    
  </div>
</div>



        
      
    </div>
    <!-- Custom Files bottomMeta begin -->
    
    <!-- Custom Files bottomMeta end -->
  </div>


  
  

  
    <div class="prev-next">
      
        <a class='prev' href='/2024/02/23/%E5%8D%95%E4%BD%93-MVC%E6%9E%B6%E6%9E%84/'>
          <p class='title'><i class="fa-solid fa-chevron-left" aria-hidden="true"></i>Feb 23, 2024</p>
          <p class='content'>JavaWEB MVC写Java Web项目时会发现，一个中型或者大型项目 随着代码的增多，会发现：代码既可以写在src目录下，也可以写在WebContent目录下。src下可以建很多包 ，We...</p>
        </a>
      
      
        <a class='next' href='/2024/02/23/Vue%E5%B7%A5%E7%A8%8B%E5%8C%96%E8%B5%84%E6%96%99/'>
          <p class='title'>Feb 23, 2024<i class="fa-solid fa-chevron-right" aria-hidden="true"></i></p>
          <p class='content'>Vue工程化指南组件详解
组件就是一个个的html文件本质上，因为他具备三个东西，script，style以及html 骨架

例如我们之前定义的一个html文件:
axios.html
123...</p>
        </a>
      
    </div>
  
  <!-- Custom Files postEnd begin-->
  
  <!-- Custom Files postEnd end-->
</article>


  


  <article class="post white-box shadow floatable blur" id="comments">
    <span hidden>
      <meta itemprop="discussionUrl" content="/2024/02/23/%E5%8D%95%E4%BD%93-JSP/index.html#comments">
    </span>
    <p ct><i class='fa-solid fa-comments'></i> 评论</p>
    

    <div id="layoutHelper-comments"></div>

  </article>






</div>
<aside id='l_side' itemscope itemtype="http://schema.org/WPSideBar">
  

  
    
    
      
    
  


<div class="widget-sticky pjax">

  
  


  <section class="widget toc-wrapper desktop mobile " id="toc-div" >
    
  <header>
    
      <i class="fa-solid fa-list fa-fw" aria-hidden="true"></i><span class='name'>本文目录</span>
    
  </header>


    <div class='content'>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81JSP%E6%A6%82%E8%BF%B0"><span class="toc-text">一、JSP概述</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-1-Servlet%E4%BD%BF%E7%94%A8%E7%9A%84%E4%B8%8D%E8%B6%B3"><span class="toc-text">1.1 Servlet使用的不足</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-2-JSP%E7%AE%80%E4%BB%8B"><span class="toc-text">1.2 JSP简介</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81JSP%E5%85%A5%E9%97%A8%E6%A1%88%E4%BE%8B"><span class="toc-text">二、JSP入门案例</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-%E6%A1%88%E4%BE%8B%E5%87%86%E5%A4%87"><span class="toc-text">2.1 案例准备</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-1-%E5%88%9B%E5%BB%BA%E6%95%B0%E6%8D%AE%E5%BA%93%E6%95%B0%E6%8D%AE%E8%A1%A8"><span class="toc-text">2.1.1 创建数据库数据表</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-2-%E5%88%9B%E5%BB%BAweb%E9%A1%B9%E7%9B%AE"><span class="toc-text">2.1.2 创建web项目</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-3-%E5%AE%8C%E6%88%90JDBC%E5%87%86%E5%A4%87"><span class="toc-text">2.1.3 完成JDBC准备</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2-%E5%AE%8C%E6%88%90%E6%A1%88%E4%BE%8B%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C"><span class="toc-text">2.2 完成案例的数据库操作</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-1-%E5%88%9B%E5%BB%BA%E5%AE%9E%E4%BD%93%E7%B1%BB"><span class="toc-text">2.2.1 创建实体类</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-2-%E5%88%9B%E5%BB%BADAO%E7%B1%BB%E5%AE%8C%E6%88%90%E6%93%8D%E4%BD%9C"><span class="toc-text">2.2.2 创建DAO类完成操作</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-3-JSP%E5%91%88%E7%8E%B0%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5"><span class="toc-text">2.3 JSP呈现动态网页</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3-1-%E5%88%9B%E5%BB%BABookListServlet"><span class="toc-text">2.3.1 创建BookListServlet</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3-2-%E5%88%9B%E5%BB%BAJSP%E9%A1%B5%E9%9D%A2"><span class="toc-text">2.3.2 创建JSP页面</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-3-3-%E5%9C%A8JSP%E9%A1%B5%E9%9D%A2%E4%B8%AD%E6%98%BE%E7%A4%BA%E5%8A%A8%E6%80%81%E6%95%B0%E6%8D%AE"><span class="toc-text">2.3.3 在JSP页面中显示动态数据</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%89%E3%80%81JSP%E5%BC%80%E5%8F%91%E8%AF%A6%E8%A7%A3"><span class="toc-text">三、JSP开发详解</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-1-JSP%E5%92%8CServlet"><span class="toc-text">3.1 JSP和Servlet</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-2-JSP%E5%BC%80%E5%8F%91%E7%9A%84%E8%AF%AD%E6%B3%95%E8%A7%84%E5%88%99"><span class="toc-text">3.2 JSP开发的语法规则</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2-1-JSP%E6%96%87%E6%A1%A3%E8%A7%84%E8%8C%83"><span class="toc-text">3.2.1 JSP文档规范</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2-2-Java%E8%84%9A%E6%9C%AC"><span class="toc-text">3.2.2 Java脚本</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2-3-JSP%E6%B3%A8%E9%87%8A"><span class="toc-text">3.2.3 JSP注释</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3-JSP%E7%BC%96%E8%AF%91%E6%8C%87%E4%BB%A4"><span class="toc-text">3.3 JSP编译指令</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3-1"><span class="toc-text">3.3.1 &lt;%@ page%&gt;</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3-2"><span class="toc-text">3.3.2 &lt;%@ include %&gt;</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3-3"><span class="toc-text">3.3.3 &lt;%@ taglib %&gt;</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-4-JSP%E5%8A%A8%E4%BD%9C%E6%8C%87%E4%BB%A4"><span class="toc-text">3.4 JSP动作指令</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4-1-jsp-include"><span class="toc-text">3.4.1 jsp:include</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4-2-jsp-userBean"><span class="toc-text">3.4.2 jsp:userBean</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4-3-jsp-setProperty"><span class="toc-text">3.4.3 jsp:setProperty</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4-4-jsp-getProperty"><span class="toc-text">3.4.4 jsp:getProperty</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4-5-jsp-forward"><span class="toc-text">3.4.5 jsp:forward</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4-6-jsp-param"><span class="toc-text">3.4.6 jsp:param</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-5-JSP%E4%B9%9D%E5%A4%A7%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1"><span class="toc-text">3.5 JSP九大内置对象</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-6-JSP%E5%9B%9B%E5%A4%A7%E5%9F%9F%E5%AF%B9%E8%B1%A1"><span class="toc-text">3.6 JSP四大域对象</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-6-1-pageContext"><span class="toc-text">3.6.1 pageContext</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-6-2-request"><span class="toc-text">3.6.2 request</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-6-3-session"><span class="toc-text">3.6.3 session</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-6-4-application"><span class="toc-text">3.6.4 application</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-6-5-%E4%BD%BF%E7%94%A8%E5%9F%9F%E5%AF%B9%E8%B1%A1%E4%BC%A0%E5%80%BC%E7%A4%BA%E4%BE%8B"><span class="toc-text">3.6.5 使用域对象传值示例</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-7-JSP%E5%BC%80%E5%8F%91%E5%BA%94%E7%94%A8"><span class="toc-text">3.7 JSP开发应用</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9B%9B%E3%80%81EL%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="toc-text">四、EL表达式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-1-%E4%BB%80%E4%B9%88%E6%98%AFEL"><span class="toc-text">4.1 什么是EL?</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-EL%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BA%94%E7%94%A8"><span class="toc-text">4.2 EL表达式应用</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2-1-%E5%AE%9E%E4%BD%93%E7%B1%BB"><span class="toc-text">4.2.1 实体类</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2-2-TestServlet%E7%B1%BB"><span class="toc-text">4.2.2 TestServlet类</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-2-3-test-jsp"><span class="toc-text">4.2.3 test.jsp</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-3-EL%E8%AE%BF%E9%97%AE%E5%9F%9F%E5%AF%B9%E8%B1%A1"><span class="toc-text">4.3 EL访问域对象</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-3-1-key-%E8%8E%B7%E5%8F%96%E5%93%AA%E4%B8%AA%E5%9F%9F%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%95%B0%E6%8D%AE%E5%91%A2%EF%BC%9F"><span class="toc-text">4.3.1 ${key}获取哪个域对象的数据呢？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-3-2-%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8EL%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E5%9F%9F%E5%AF%B9%E8%B1%A1%E6%95%B0%E6%8D%AE%EF%BC%9F"><span class="toc-text">4.3.2 如何使用EL获取指定域对象数据？</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-4-EL%E7%9A%84%E9%9A%90%E5%BC%8F%E5%AF%B9%E8%B1%A1"><span class="toc-text">4.4 EL的隐式对象</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-5-EL%E7%9A%84%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-text">4.5 EL的运算符</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#4-5-1-%E7%AE%97%E6%9C%AF%E8%BF%90%E7%AE%97"><span class="toc-text">4.5.1 算术运算</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-5-2-%E5%85%B3%E7%B3%BB%E6%AF%94%E8%BE%83"><span class="toc-text">4.5.2 关系比较</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-5-3-%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97"><span class="toc-text">4.5.3 逻辑运算</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-5-4-%E5%88%A4%E7%A9%BA"><span class="toc-text">4.5.4 判空</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%94%E3%80%81JSTL"><span class="toc-text">五、JSTL</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#5-1-JSTL%E7%AE%80%E4%BB%8B"><span class="toc-text">5.1 JSTL简介</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-2-JSTL%E7%9A%84%E5%BC%95%E5%85%A5%E6%AD%A5%E9%AA%A4"><span class="toc-text">5.2 JSTL的引入步骤</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-3-JSTL%E6%A0%B8%E5%BF%83%E6%A0%87%E7%AD%BE%E5%BA%93"><span class="toc-text">5.3 JSTL核心标签库</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#5-3-1-c-if"><span class="toc-text">5.3.1 c:if</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-3-2-c-choose"><span class="toc-text">5.3.2 c:choose</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5-3-3-c-forEach"><span class="toc-text">5.3.3 c:forEach</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-4-JSTL%E8%BD%AC%E6%8D%A2%E6%A0%87%E7%AD%BE"><span class="toc-text">5.4 JSTL转换标签</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%AD%E3%80%81Servlet%E5%92%8CJSP%E7%9A%84%E7%BB%BC%E5%90%88%E6%A1%88%E4%BE%8B"><span class="toc-text">六、Servlet和JSP的综合案例</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#6-1-%E4%B9%A6%E5%9F%8E%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E4%B8%9A%E5%8A%A1%E6%B5%81%E7%A8%8B"><span class="toc-text">6.1 书城后台管理系统业务流程</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-2-%E9%A1%B9%E7%9B%AE%E7%9A%84MVC%E5%88%86%E5%B1%82%E6%9E%B6%E6%9E%84"><span class="toc-text">6.2 项目的MVC分层架构</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-3-%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AE%BE%E8%AE%A1"><span class="toc-text">6.3 数据库设计</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-4-web%E9%A1%B9%E7%9B%AE%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA"><span class="toc-text">6.4 web项目环境搭建</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-5-%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AE%BF%E9%97%AE%E5%AE%9E%E7%8E%B0"><span class="toc-text">6.5 数据库访问实现</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#6-5-1-%E7%AE%A1%E7%90%86%E5%91%98%E7%99%BB%E5%BD%95%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C"><span class="toc-text">6.5.1 管理员登录的数据库操作</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-5-2-%E5%9B%BE%E4%B9%A6%E7%AE%A1%E7%90%86%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93%E6%93%8D%E4%BD%9C"><span class="toc-text">6.5.2 图书管理的数据库操作</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-6-%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1"><span class="toc-text">6.6 网页设计</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-7-%E4%B8%9A%E5%8A%A1%E5%B1%82%E5%AE%9E%E7%8E%B0"><span class="toc-text">6.7 业务层实现</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#6-7-1-%E7%AE%A1%E7%90%86%E5%91%98%E7%99%BB%E5%BD%95%E4%B8%9A%E5%8A%A1"><span class="toc-text">6.7.1 管理员登录业务</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-7-2-%E5%9B%BE%E4%B9%A6%E7%AE%A1%E7%90%86%E4%B8%9A%E5%8A%A1%E5%AE%9E%E7%8E%B0"><span class="toc-text">6.7.2 图书管理业务实现</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#6-8-%E5%8A%9F%E8%83%BD%E6%B5%81%E7%A8%8B%E5%AE%9E%E7%8E%B0"><span class="toc-text">6.8 功能流程实现</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#6-8-1-%E5%88%9B%E5%BB%BAJSP%E5%8F%8AServlet%E7%B1%BB"><span class="toc-text">6.8.1 创建JSP及Servlet类</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-8-2-%E7%AE%A1%E7%90%86%E5%91%98%E7%99%BB%E5%BD%95"><span class="toc-text">6.8.2 管理员登录</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-8-3-%E6%B7%BB%E5%8A%A0%E5%9B%BE%E4%B9%A6"><span class="toc-text">6.8.3 添加图书</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-8-4-%E5%9B%BE%E4%B9%A6%E5%88%97%E8%A1%A8"><span class="toc-text">6.8.4 图书列表</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-8-5-%E5%88%A0%E9%99%A4%E5%9B%BE%E4%B9%A6"><span class="toc-text">6.8.5 删除图书</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6-8-6-%E4%BF%AE%E6%94%B9%E5%9B%BE%E4%B9%A6"><span class="toc-text">6.8.6 修改图书</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%83%E3%80%81%E5%88%86%E9%A1%B5%E5%8A%9F%E8%83%BD%E5%AE%9E%E7%8E%B0"><span class="toc-text">七、分页功能实现</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#7-1-%E5%88%86%E9%A1%B5%E6%A6%82%E5%BF%B5"><span class="toc-text">7.1 分页概念</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-2-%E5%88%86%E9%A1%B5%E5%AE%9E%E7%8E%B0%E6%80%9D%E8%B7%AF"><span class="toc-text">7.2 分页实现思路</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-3-%E5%88%86%E9%A1%B5%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0"><span class="toc-text">7.3 分页代码实现</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#7-3-1-BookDAO"><span class="toc-text">7.3.1 BookDAO</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-3-2-BookService"><span class="toc-text">7.3.2 BookService</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-3-3-BookListServlet"><span class="toc-text">7.3.3 BookListServlet</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-4-book-list-jsp"><span class="toc-text">7.4 book-list.jsp</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#7-4-PageHelper%E5%B0%81%E8%A3%85"><span class="toc-text">7.4 PageHelper封装</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#7-4-1-PageHelper%E5%B0%81%E8%A3%85%E6%80%9D%E8%B7%AF"><span class="toc-text">7.4.1 PageHelper封装思路</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-4-2-%E5%88%9B%E5%BB%BA%E5%88%86%E9%A1%B5%E5%B8%AE%E5%8A%A9%E7%B1%BBPageHelper"><span class="toc-text">7.4.2  创建分页帮助类PageHelper</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-4-3-BookService"><span class="toc-text">7.4.3 BookService</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-4-4-BookListServlet"><span class="toc-text">7.4.4 BookListServlet</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7-4-5-book-list-jsp"><span class="toc-text">7.4.5 book-list.jsp</span></a></li></ol></li></ol></li></ol>
    </div>
  </section>

  

</div>


<!-- 没有 pjax 占位会报错 万恶的 pjax -->

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <div class="pjax">
    <!-- pjax占位 -->
  </div>

  <!-- Custom Files side begin -->
  
  <!-- Custom Files side end -->
</aside>



          <!--此文件用来存放一些不方便取值的变量-->
<!--思路大概是将值藏到重加载的区域内-->

<pjax>
<script>
  window.pdata={}
  pdata.ispage=false;
  pdata.commentPath="";
  pdata.commentPlaceholder="";
  pdata.commentConfig={};
  //  see: /layout/_partial/scripts/_ctrl/coverCtrl.ejs
  
    // header
    var l_header=document.getElementById("l_header");
    
    l_header.classList.add("show");
    
    
      // cover
      var cover_wrapper=document.querySelector('#l_cover .cover-wrapper');
      var scroll_down=document.getElementById('scroll-down');
      cover_wrapper.id="none";
      cover_wrapper.style.display="none";
      scroll_down.style.display="none";
    
  
</script>
</pjax>
        </div>
        
  
  <footer class="footer clearfix"  itemscope itemtype="http://schema.org/WPFooter">
    <br><br>
    
      
        <div class="aplayer-container">
          


        </div>
      
    
      
        <br>
        <div class="social-wrapper" itemprop="about" itemscope itemtype="http://schema.org/Thing">
          
            
          
            
          
            
          
        </div>
      
    
      
        <div><p>Blog content follows the <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en">Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) License</a></p>
</div>
      
    
      
        
          <div><p><span id="lc-sv">本站总访问量为 <span id='number'><i class="fa-solid fa-loader fa-spin fa-fw" aria-hidden="true"></i></span> 次</span> <span id="lc-uv">访客数为 <span id='number'><i class="fa-solid fa-loader fa-spin fa-fw" aria-hidden="true"></i></span> 人</span></p>
</div>
        
      
    
      
        Use
        <a href="https://github.com/volantis-x/hexo-theme-volantis/#5.8.0" target="_blank" class="codename">Volantis</a>
        as theme
      
    
      
        <div class='copyright'>
        <p><a href="/">Copyright © since 2017 XXX</a></p>

        </div>
      
    
    <!-- Custom Files footer begin-->
    
    <!-- Custom Files footer end-->
  </footer>


        <a id="s-top" class="fa-solid fa-arrow-up fa-fw" href="/" onclick="return false;" title="top"></a>
      </div>
    </div>
    <div>
      <script>
  /******************** volantis.dom ********************************/
  // 页面选择器 将dom对象缓存起来 see: /source/js/app.js etc.
  volantis.dom.bodyAnchor = volantis.dom.$(document.getElementById("safearea")); // 页面主体
  volantis.dom.topBtn = volantis.dom.$(document.getElementById('s-top')); // 向上
  volantis.dom.wrapper = volantis.dom.$(document.getElementById('wrapper')); // 整个导航栏
  volantis.dom.coverAnchor = volantis.dom.$(document.querySelector('#l_cover .cover-wrapper')); // 1个
  volantis.dom.switcher = volantis.dom.$(document.querySelector('#l_header .switcher .s-search')); // 搜索按钮   移动端 1个
  volantis.dom.header = volantis.dom.$(document.getElementById('l_header')); // 移动端导航栏
  volantis.dom.search = volantis.dom.$(document.querySelector('#l_header .m_search')); // 搜索框 桌面端 移动端 1个
  volantis.dom.mPhoneList = volantis.dom.$(document.querySelectorAll('#l_header .m-phone .list-v')); //  手机端 子菜单 多个
</script>

<script>
  
  volantis.css("https://unpkg.com/volantis-static@0.0.1654736714924/libs/@fortawesome/fontawesome-free/css/all.min.css");
  
  
  
</script>

<!-- required -->


<!-- internal -->

<script src="/js/app.js"></script>






<!-- rightmenu要在darkmode之前（ToggleButton） darkmode要在comments之前（volantis.dark.push）-->



<script>
  function loadIssuesJS() {
    
      const sites_api = document.getElementById('sites-api');
      if (sites_api != undefined && typeof SitesJS === 'undefined') {
        volantis.js("/js/plugins/tags/sites.js")
      }
    
    
      const friends_api = document.getElementById('friends-api');
      if (friends_api != undefined && typeof FriendsJS === 'undefined') {
        volantis.js("/js/plugins/tags/friends.js")
      }
    
    
      const contributors_api = document.getElementById('contributors-api');
      if (contributors_api != undefined && typeof ContributorsJS === 'undefined') {
        volantis.js("/js/plugins/tags/contributors.js")
      }
    
  };
  loadIssuesJS()
  volantis.pjax.push(()=>{
    loadIssuesJS();
  })

</script>




  <script defer src="https://unpkg.com/volantis-static@0.0.1654736714924/libs/vanilla-lazyload/dist/lazyload.min.js"></script>
<script>
  // https://www.npmjs.com/package/vanilla-lazyload
  // Set the options globally
  // to make LazyLoad self-initialize
  window.lazyLoadOptions = {
    elements_selector: ".lazyload",
    threshold: 0
  };
  // Listen to the initialization event
  // and get the instance of LazyLoad
  window.addEventListener(
    "LazyLoad::Initialized",
    function (event) {
      window.lazyLoadInstance = event.detail.instance;
    },
    false
  );
  document.addEventListener('DOMContentLoaded', function () {
    lazyLoadInstance.update();
  });
  document.addEventListener('pjax:complete', function () {
    lazyLoadInstance.update();
  });
</script>




  

<script>
  window.FPConfig = {
	delay: 0,
	ignoreKeywords: ["#"],
	maxRPS: 6,
	hoverDelay: 0
  };
</script>
<script defer src="https://unpkg.com/volantis-static@0.0.1654736714924/libs/flying-pages/flying-pages.min.js"></script>









      <script>
  volantis.layoutHelper("comments",`<div id="giscus_container"></div>`)

  volantis.giscus = {};

  function check_giscus() {
    if (volantis.dark.mode === "dark") {
      volantis.giscus.Theme = 'dark';
    } else {
      volantis.giscus.Theme = 'light';
    }

    return document.getElementById("giscus_container");
  }

  function pjax_giscus() {
    const HEAD = check_giscus();
    if (!HEAD) return;
    let cfg = Object.assign({"theme":{"light":"light","dark":"dark"}},pdata.commentConfig)
    const script = document.createElement('script');
    script.setAttribute('src', 'https://giscus.app/client.js');
    Object.keys(cfg).forEach(k=>{
      if (k != "theme") {
        script.setAttribute('data-'+k, cfg[k]);
      }
    })
    script.setAttribute('data-theme', volantis.giscus.Theme);
    script.setAttribute('crossorigin', "anonymous");
    HEAD.appendChild(script);
  }

  function dark_giscus() {
    const HEAD = check_giscus();
    if (!HEAD) return;

    const message = {
      setConfig: {
        theme: volantis.giscus.Theme
      }
    };
    const giscusIframe = document.querySelector('iframe.giscus-frame');
    giscusIframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
  }
  pjax_giscus();
  volantis.pjax.push(pjax_giscus);
  volantis.dark.push(dark_giscus);
</script>

    





<!-- optional -->

  <script>
  const SearchServiceDataPathRoot = ("/" || "/").endsWith("/") ?
    "/" || "/" :
    "//" || "/";
  const SearchServiceDataPath = SearchServiceDataPathRoot + "content.json";

  function loadSearchScript() {
    // see: layout/_partial/scripts/_ctrl/cdnCtrl.ejs
    return volantis.js("/js/search/hexo.js");
  }

  function loadSearchService() {
    loadSearchScript();
    document.querySelectorAll(".input.u-search-input").forEach((e) => {
      e.removeEventListener("focus", loadSearchService, false);
    });

    document.querySelectorAll(".u-search-form").forEach((e) => {
      e.addEventListener("submit", (event) => {
        event.preventDefault();
      }, false);
    });
  }

  // 打开并搜索 字符串 s
  function OpenSearch(s) {
    if (typeof SearchService === 'undefined')
      loadSearchScript().then(() => {
        SearchService.setQueryText(s);
        SearchService.search();
      });
    else {
      SearchService.setQueryText(s);
      SearchService.search();
    }
  }

  // 访问含有 ?s=xxx  的链接时打开搜索 // 与搜索引擎 structured data 相关: /scripts/helpers/structured-data/lib/config.js
  if (window.location.search && /^\?s=/g.test(window.location.search)) {
    let queryText = decodeURI(window.location.search)
      .replace(/\ /g, "-")
      .replace(/^\?s=/g, "");
    OpenSearch(queryText);
  }

  // 搜索输入框获取焦点时加载搜索
  document.querySelectorAll(".input.u-search-input").forEach((e) => {
    e.addEventListener("focus", loadSearchService, false);
  });
</script>







  <script>



  function pjax_highlightjs_copyCode(){
    if (!(document.querySelector(".highlight .code pre") ||
      document.querySelector(".article pre code"))) {
      return;
    }
    VolantisApp.utilCopyCode(".highlight .code pre, .article pre code")
  }
  volantis.requestAnimationFrame(pjax_highlightjs_copyCode)
  volantis.pjax.push(pjax_highlightjs_copyCode)

</script>












  <script>
  function load_swiper() {
    if (!document.querySelectorAll(".swiper-container")[0]) return;
    volantis.css("https://unpkg.com/volantis-static@0.0.1654736714924/libs/swiper/swiper-bundle.min.css");
    volantis.js("https://unpkg.com/volantis-static@0.0.1654736714924/libs/swiper/swiper-bundle.min.js").then(() => {
      pjax_swiper();
    });
  }

  load_swiper();

  function pjax_swiper() {
    volantis.swiper = new Swiper('.swiper-container', {
      slidesPerView: 'auto',
      spaceBetween: 8,
      centeredSlides: true,
      loop: true,
      pagination: {
        el: '.swiper-pagination',
        clickable: true,
      },
      navigation: {
        nextEl: '.swiper-button-next',
        prevEl: '.swiper-button-prev',
      },
    });
  }

  volantis.pjax.push(() => {
    if (!document.querySelectorAll(".swiper-container")[0]) return;
    if (typeof volantis.swiper === "undefined") {
      load_swiper();
    } else {
      pjax_swiper();
    }
  });
</script>


<!-- pjax 标签必须存在于所有页面 否则 pjax error -->
<pjax>

</pjax>

<script>
  function listennSidebarTOC() {
    const navItems = document.querySelectorAll(".toc li");
    if (!navItems.length) return;
    let targets = []
    const sections = [...navItems].map((element) => {
      const link = element.querySelector(".toc-link");
      const target = document.getElementById(
        decodeURI(link.getAttribute("href")).replace("#", "")
      );
      targets.push(target)
      // 解除 a 标签 href 的 锚点定位, a 标签 href 的 锚点定位 会随机启用?? 产生错位???
      link.setAttribute("onclick","return false;")
      link.setAttribute("toc-action","toc-"+decodeURI(link.getAttribute("href")).replace("#", ""))
      link.setAttribute("href","/")
      // 配置 点击 触发新的锚点定位
      link.addEventListener("click", (event) => {
        event.preventDefault();
        // 这里的 addTop 是通过错位使得 toc 自动展开.
        volantis.scroll.to(target,{addTop: 5, observer:true})
        // Anchor id
        history.pushState(null, document.title, "#" + target.id);
      });
      return target;
    });

    function activateNavByIndex(target) {
      if (target.classList.contains("active-current")) return;

      document.querySelectorAll(".toc .active").forEach((element) => {
        element.classList.remove("active", "active-current");
      });
      target.classList.add("active", "active-current");
      let parent = target.parentNode;
      while (!parent.matches(".toc")) {
        if (parent.matches("li")) parent.classList.add("active");
        parent = parent.parentNode;
      }
    }

    // 方案一：
    volantis.activateNavIndex=0
    activateNavByIndex(navItems[volantis.activateNavIndex])
    volantis.scroll.push(()=>{
      if (targets[0].getBoundingClientRect().top >= 0) {
        volantis.activateNavIndex = 0
      }else if (targets[targets.length-1].getBoundingClientRect().top < 0) {
        volantis.activateNavIndex = targets.length-1
      } else {
        for (let index = 0; index < targets.length; index++) {
          const target0 = targets[index];
          const target1 = targets[(index+1)%targets.length];
          if (target0.getBoundingClientRect().top < 0&&target1.getBoundingClientRect().top >= 0) {
            volantis.activateNavIndex=index
            break;
          }
        }
      }
      activateNavByIndex(navItems[volantis.activateNavIndex])
    })

    // 方案二：
    // IntersectionObserver 不是完美精确到像素级别 也不是低延时性的
    // function findIndex(entries) {
    //   let index = 0;
    //   let entry = entries[index];
    //   if (entry.boundingClientRect.top > 0) {
    //     index = sections.indexOf(entry.target);
    //     return index === 0 ? 0 : index - 1;
    //   }
    //   for (; index < entries.length; index++) {
    //     if (entries[index].boundingClientRect.top <= 0) {
    //       entry = entries[index];
    //     } else {
    //       return sections.indexOf(entry.target);
    //     }
    //   }
    //   return sections.indexOf(entry.target);
    // }
    // function createIntersectionObserver(marginTop) {
    //   marginTop = Math.floor(marginTop + 10000);
    //   let intersectionObserver = new IntersectionObserver(
    //     (entries, observe) => {
    //       let scrollHeight = document.documentElement.scrollHeight;
    //       if (scrollHeight > marginTop) {
    //         observe.disconnect();
    //         createIntersectionObserver(scrollHeight);
    //         return;
    //       }
    //       let index = findIndex(entries);
    //       activateNavByIndex(navItems[index]);
    //     }, {
    //       rootMargin: marginTop + "px 0px -100% 0px",
    //       threshold: 0,
    //     }
    //   );
    //   sections.forEach((element) => {
    //     element && intersectionObserver.observe(element);
    //   });
    // }
    // createIntersectionObserver(document.documentElement.scrollHeight);
  }

  document.addEventListener("DOMContentLoaded", ()=>{
    volantis.requestAnimationFrame(listennSidebarTOC)
  });
  document.addEventListener("pjax:success", ()=>{
    volantis.requestAnimationFrame(listennSidebarTOC)
  });
</script>



<script>
  document.onreadystatechange = function () {
    if (document.readyState == 'complete') {
      // 页面加载完毕 样式加载失败，或是当前网速慢，或是开启了省流模式
      const { saveData, effectiveType } = navigator.connection || navigator.mozConnection || navigator.webkitConnection || {}
      if (getComputedStyle(document.querySelector("#safearea"), null)["display"] == "none" || saveData || /2g/.test(effectiveType)) {
        document.querySelectorAll(".reveal").forEach(function (e) {
          e.style["opacity"] = "1";
        });
        document.querySelector("#safearea").style["display"] = "block";
      }
    }
  }
</script>


  <script type="application/ld+json">[{"@context":"http://schema.org","@type":"Organization","name":"欢迎来到我的个人博客~","url":"http://8.219.11.28/","logo":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png","width":192,"height":192}},{"@context":"http://schema.org","@type":"Person","name":"天明","image":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png"},"url":"http://8.219.11.28/","sameAs":["https://github.com/volantis-x"],"description":"这些技术大部分是自己总结的，非官方"},{"@context":"http://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"http://8.219.11.28/","name":"欢迎来到我的个人博客~"}},{"@type":"ListItem","position":3,"item":{"@id":"http://8.219.11.28/2024/02/23/单体-JSP/"}}]},{"@context":"http://schema.org","@type":"WebSite","name":"欢迎来到我的个人博客~","url":"http://8.219.11.28/","keywords":null,"description":"这些技术大部分是自己总结的，非官方","author":{"@type":"Person","name":"天明","image":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png"},"url":"http://8.219.11.28/","description":"这些技术大部分是自己总结的，非官方"},"publisher":{"@type":"Organization","name":"欢迎来到我的个人博客~","url":"http://8.219.11.28/","logo":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png","width":192,"height":192}},"potentialAction":{"@type":"SearchAction","name":"Site Search","target":{"@type":"EntryPoint","urlTemplate":"http://8.219.11.28?s={search_term_string}"},"query-input":"required name=search_term_string"}},{"@context":"http://schema.org","@type":"BlogPosting","description":"这些技术大部分是自己总结的，非官方","inLanguage":"en","mainEntityOfPage":{"@type":"WebPage","@id":"http://8.219.11.28/2024/02/23/%E5%8D%95%E4%BD%93-JSP/"},"author":{"@type":"Person","name":"天明","image":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png"},"url":"http://8.219.11.28/"},"publisher":{"@type":"Organization","name":"欢迎来到我的个人博客~","logo":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png","width":192,"height":192}},"url":"http://8.219.11.28/2024/02/23/%E5%8D%95%E4%BD%93-JSP/","wordCount":0,"datePublished":"2024-02-23T14:27:45.421Z","dateModified":"2024-01-07T15:46:22.673Z","image":{"@type":"ImageObject","url":"https://unpkg.com/volantis-static@0.0.1654736714924/media/org.volantis/blog/favicon/android-chrome-192x192.png","width":192,"height":192}}]</script>



      
        <!--
  pjax重载区域接口：
  1.  <pjax></pjax> 标签 pjax 标签必须存在于所有页面 否则 pjax error
  2.  script[data-pjax]
  3.  .pjax-reload script
  4.  .pjax
-->



<script src="https://unpkg.com/volantis-static@0.0.1654736714924/libs/pjax/pjax.min.js"></script>


<script>
    var pjax;
    document.addEventListener('DOMContentLoaded', function () {
      pjax = new Pjax({
        elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox]):not([onclick="return false;"]):not([onclick="return!1"]):not([target="_blank"]):not([target="view_window"]):not([href$=".xml"])',
        selectors: [
          "head title",
          "head meta[name=keywords]",
          "head meta[name=description]",
          
          "#l_main",
          "#pjax-header-nav-list",
          ".pjax",
          "pjax", // <pjax></pjax> 标签
          "script[data-pjax], .pjax-reload script" // script标签添加data-pjax 或 script标签外层添加.pjax-reload 的script代码段重载
        ],
        cacheBust: false,   // url 地址追加时间戳，用以避免浏览器缓存
        timeout: 5000,
        
      });
    });

    document.addEventListener('pjax:send', function (e) {
      //window.stop(); // 相当于点击了浏览器的停止按钮

      try {
        var currentUrl = window.location.pathname;
        var targetUrl = e.triggerElement.href;
        var banUrl = [""];
        if (banUrl[0] != "") {
          banUrl.forEach(item => {
            if(currentUrl.indexOf(item) != -1 || targetUrl.indexOf(item) != -1) {
              window.location.href = targetUrl;
            }
          });
        }
      } catch (error) {}

      // 使用 volantis.pjax.send 方法传入pjax:send回调函数 参见layout/_partial/scripts/global.ejs
      volantis.pjax.method.send.start();
    });

    document.addEventListener('pjax:complete', function () {
      // 使用 volantis.pjax.push 方法传入重载函数 参见layout/_partial/scripts/global.ejs
      volantis.pjax.method.complete.start();
    });

    document.addEventListener('pjax:error', function (e) {
      if(volantis.debug) {
        console.error(e);
        console.log('pjax error: \n' + JSON.stringify(e));
      }else{
        // 使用 volantis.pjax.error 方法传入pjax:error回调函数 参见layout/_partial/scripts/global.ejs
        volantis.pjax.method.error.start();
        window.location.href = e.triggerElement.href;
      }
    });
</script>

      
    </div>
    <!-- import body_end begin-->
    <!-- import body_end end-->
    <!-- Custom Files bodyEnd begin-->
    
    <!-- Custom Files bodyEnd end-->
    <!-- front-matter body_end begin -->
    <!-- front-matter body_end end -->
  </body>
</html>
